一眼切题的感觉太爽了= =
设 表示节点 不是绿色时子树 最多有多少绿色节点, 表示节点 是绿色时子树 最多有多少绿色节点。
因为合并状态的时候与当前节点是否为绿色有关,所以要讨论节点是否为绿色。
还是感觉敲码的时间有点长……
#include <cstdio>
#include <cstring>
#include <vector>
const int N = 500005;
char s[N];
int n, f[N][2], g[N][2], ch[N][2];
int max(int x, int y) {
if (x >= y) return x; return y;
}
int min(int x, int y) {
if (x <= y) return x; return y;
}
void build(int cur, int fa) {
if (ch[fa][0]) ch[fa][1] = cur;
else ch[fa][0] = cur;
if (s[cur-1] == '0') return;
build(++n, cur);
if (s[cur-1] == '2') build(++n, cur);
}
void dp(int u) {
if (ch[u][0]) dp(ch[u][0]);
if (ch[u][1]) dp(ch[u][1]);
f[u][1] = f[ch[u][0]][0] + f[ch[u][1]][0] + 1;
f[u][0] = max(f[ch[u][0]][0] + f[ch[u][1]][1], f[ch[u][0]][1] + f[ch[u][1]][0]);
g[u][1] = g[ch[u][0]][0] + g[ch[u][1]][0] + 1;
g[u][0] = min(g[ch[u][0]][0] + g[ch[u][1]][1], g[ch[u][0]][1] + g[ch[u][1]][0]);
}
int main() {
scanf("%s", s);
build(++n, 0);
dp(1);
printf("%d %d\n", max(f[1][0], f[1][1]), min(g[1][0], g[1][1]));
return 0;
}