题目链接:点我啊╭(╯^╰)╮
D. Neko and Aki’s Prank
题目大意:
对括号序列的构成过程构造一棵树,对这棵树求最大边独立
解题思路:
可以记忆化搜索,同时贪心,思路是一层一层的加边
那么对于dp的方法,因为是括号序列,每加上一个括号,它的所有连边数(其实说的不准确,自己体会吧)也可以根据以前的状态求出来
对于dp求最大边独立的话,自己画出
n
=
3
n=3
n=3 的情况,可以看出最佳情况就是上面所说的一层层加边,对等于括号的数量,即奇数或者偶数加边
代码思路:
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示有
j
j
j 个左括号、
i
i
i 个右括号的情况(已修改),那么
转移就只有一行了… 2333333333
核心:神奇dp
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int mod = 1e9 + 7;
int n;
ll dp[1015][1015];
int main() {
scanf("%d", &n);
for (int l=0; l<=n; ++l)
for (int r=l; r<=n; ++r)
dp[l][r] = ((l ? dp[l-1][r] : 0) + dp[l][r-1] + (l+r & 1)) % mod;
printf("%lld", dp[n][n]);
}
E. Neko and Flashback
题目大意:
给一个序列
a
a
a
序列
b
b
b 表示
a
a
a 相邻的较小值
序列
c
c
c 表示
a
a
a 相邻的较大值
给一个序列
p
p
p
序列
b
′
b′
b′ 表示
b
p
i
b_{p_i}
bpi
序列
c
′
c′
c′ 表示
c
p
i
c_{p_i}
cpi
最后给出
b
′
b′
b′,
c
′
c′
c′
求出满足的序列
a
a
a
解题思路:
构造、模拟
代码思路:
注意, m u l t i s e t multiset multiset 的 e r a s e erase erase 操作会删除所有目标值,所以想要删除指定的一个值时,必须用 f i n d find find 返回迭代器
核心:STL大法好
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 3e5 + 10;
const int mod = 1e9 + 7;
int n, even, st, b[maxn], c[maxn];
set <int> s;
map <int, int> num;
map <int, multiset<int>> mp;
vector <int> ans;
void dfs(int cur){
while(!mp[cur].empty()){
int nxt = *mp[cur].begin();
mp[cur].erase(mp[cur].begin());
mp[nxt].erase(mp[nxt].find(cur));
dfs(nxt);
}
ans.push_back(cur);
}
int main() {
scanf("%d", &n);
for(int i=0; i<n-1; i++){
scanf("%d", b+i);
s.insert(b[i]);
num[b[i]]++;
st = b[i];
}
for(int i=0; i<n-1; i++){
scanf("%d", c+i);
s.insert(c[i]);
if(c[i]<b[i]){
puts("-1");
return 0;
}
num[c[i]]++;
mp[b[i]].insert(c[i]);
mp[c[i]].insert(b[i]);
}
if(s.size()>n){
puts("-1");
return 0;
}
for(auto i : num){
if(i.second&1) even++, st = i.first;
}
if(even>2){
puts("-1");
return 0;
}
dfs(st);
if(ans.size()!=n){
puts("-1");
return 0;
}
for(auto i : ans) printf("%d ", i);
}