Description

Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
1122002010
Sample Output
5 2
题意:给定一颗有根树,可以选择染成绿色或者染成其他颜色,父亲节点相同的节点要求颜色不同,求最后最多/少有几个绿色节点
可以发现这个蓝色和红色没有用,开个数组记录一下是否染成绿色就好了,方程也很好推啊T T,第一次写树形dp也
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define ll long long
#define inf 0x7fffffff
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
return x*f;
}
int cnt,l[500000],r[500000];
void get(int x)
{
char ch=getchar();
if(ch==‘0‘) return;
cnt++;l[x]=cnt;get(l[x]);
if(ch==‘2‘){cnt++;r[x]=cnt;get(r[x]);}
}
int f[500000][2];
void dp(int x)
{
if(!x) return;
dp(l[x]);dp(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 ans1,ans2;
int main()
{
cnt=1;get(1);
dp(1);ans1=max(f[1][1],f[1][0]);
memset(f,0,sizeof(f));
dp2(1);ans2=min(f[1][1],f[1][0]);
printf("%d %d\n",ans1,ans2);
}