Description:
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Analysis:
f[x][0/1] := 表示 x 结点为非绿/绿色子树的绿色结点的最大个数
f[x][1] = f[l[x]][0] + f[r[x]][0] + 1
f[x][0] = max(f[l[x]][1] + f[r[x]][0],f[l[x]][0] + f[r[x]][1])
Code
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 500010;
int f[N][2],l[N],r[N],n;
void dfs(int p)
{
char ch = getchar();
if(ch == '0') return;
l[p] = ++n;
dfs(n);
if(ch == '2'){
r[p] = ++n;
dfs(n);
}
}
void dp1(int x)
{
if(!x) return;
dp1(l[x]);dp1(r[x]);
f[x][1] = f[l[x]][0] + f[r[x]][0] + 1;
f[x][0] = max(f[l[x]][1] + f[r[x]][0],f[l[x]][0] + f[r[x]][1]);
}
void dp2(int x)
{
if(!x) return;
dp2(l[x]);dp2(r[x]);
f[x][1] = f[l[x]][0] + f[r[x]][0] + 1;
f[x][0] = min(f[l[x]][1] + f[r[x]][0],f[l[x]][0] + f[r[x]][1]);
}
int main()
{
n = 1;
dfs(1);
dp1(1);
int ans1 = max(f[1][0],f[1][1]);
memset(f,0,sizeof(f));
dp2(1);
int ans2 = min(f[1][0],f[1][1]);
printf("%d %d
",ans1,ans2);
return 0;
}