bzoj1864 [Zjoi2006]三色二叉树
Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
1122002010
Sample Output
5 2
正解:树形$dp$。
$ZJ$水题合集,直接$dp$就行了。。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define N (500010) 6 7 using namespace std; 8 9 int f[N][3],g[N][3],cnt; 10 char s[N]; 11 12 il int gi(){ 13 RG int x=0,q=1; RG char ch=getchar(); 14 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 15 if (ch=='-') q=-1,ch=getchar(); 16 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 17 return q*x; 18 } 19 20 il void dfs(){ 21 RG int x=++cnt; 22 if (s[cnt]=='0') f[x][0]=g[x][0]=1; 23 else if (s[cnt]=='1'){ 24 RG int v=cnt+1; dfs(); 25 f[x][0]=max(f[v][1],f[v][2])+1; 26 f[x][1]=max(f[v][0],f[v][2]); 27 f[x][2]=max(f[v][0],f[v][1]); 28 g[x][0]=min(g[v][1],g[v][2])+1; 29 g[x][1]=min(g[v][0],g[v][2]); 30 g[x][2]=min(g[v][0],g[v][1]); 31 } else{ 32 RG int v1=cnt+1; dfs(); RG int v2=cnt+1; dfs(); 33 f[x][0]=max(f[v1][1]+f[v2][2],f[v1][2]+f[v2][1])+1; 34 f[x][1]=max(f[v1][0]+f[v2][2],f[v1][2]+f[v2][0]); 35 f[x][2]=max(f[v1][0]+f[v2][1],f[v1][1]+f[v2][0]); 36 g[x][0]=min(g[v1][1]+g[v2][2],g[v1][2]+g[v2][1])+1; 37 g[x][1]=min(g[v1][0]+g[v2][2],g[v1][2]+g[v2][0]); 38 g[x][2]=min(g[v1][0]+g[v2][1],g[v1][1]+g[v2][0]); 39 } 40 return; 41 } 42 43 int main(){ 44 #ifndef ONLINE_JUDGE 45 freopen("tree.in","r",stdin); 46 freopen("tree.out","w",stdout); 47 #endif 48 scanf("%s",s+1),dfs(); 49 printf("%d %d\n",max(f[1][0],max(f[1][1],f[1][2])),min(g[1][0],min(g[1][1],g[1][2]))); return 0; 50 }