1864. [ZJOI2006]三色二叉树【树形DP】

Description

Input

仅有一行,不超过500000个字符,表示一个二叉树序列。

Output

输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。

Sample Input

1122002010

Sample Output

5 2

 

f[x][1\2\3]代表x点染红绿蓝色的最多有多少个点染成绿色
g[x][1\2\3]代表最少

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define N (1000000+100)
 5 using namespace std;
 6 char st[N];
 7 int Father[N],Son[N][2];
 8 int a[N],maxn;
 9 int f[N][4],g[N][4];
10 
11 void Build(int x,int fa)
12 {
13     maxn=max(maxn,x);
14     Father[x]=fa;
15     if (!Son[fa][0]) Son[fa][0]=x;
16     else Son[fa][1]=x;
17     if (a[x]>=1) Build(x+1,x);
18     if (a[x]==2) Build(maxn+1,x);
19 }
20 
21 void Dp(int x)
22 {
23     f[x][1]=0;f[x][2]=1;f[x][3]=0;
24     g[x][1]=0;g[x][2]=1;g[x][3]=0;
25     if (Son[x][0]) Dp(Son[x][0]);
26     if (Son[x][1]) Dp(Son[x][1]);
27     f[x][1]+=max( f[Son[x][0]][2]+f[Son[x][1]][3] , f[Son[x][0]][3]+f[Son[x][1]][2] );
28     f[x][2]+=max( f[Son[x][0]][1]+f[Son[x][1]][3] , f[Son[x][0]][3]+f[Son[x][1]][1] );
29     f[x][3]+=max( f[Son[x][0]][1]+f[Son[x][1]][2] , f[Son[x][0]][2]+f[Son[x][1]][1] );
30     
31     g[x][1]+=min( g[Son[x][0]][2]+g[Son[x][1]][3] , g[Son[x][0]][3]+g[Son[x][1]][2] );
32     g[x][2]+=min( g[Son[x][0]][1]+g[Son[x][1]][3] , g[Son[x][0]][3]+g[Son[x][1]][1] );
33     g[x][3]+=min( g[Son[x][0]][1]+g[Son[x][1]][2] , g[Son[x][0]][2]+g[Son[x][1]][1] );
34 } 
35 
36 int main()
37 {
38     scanf("%s",st);
39     for (int i=0;i<=strlen(st)-1;++i)
40         a[i+1]=st[i]-'0';
41     Build(1,0);
42     Son[0][0]=Son[0][1]=0;
43     Dp(1);
44     printf("%d ",max(max(f[1][1],f[1][2]),f[1][3]));
45     printf("%d",min(min(g[1][1],g[1][2]),g[1][3]));
46 }
posted @ 2018-03-31 08:15  Refun  阅读(142)  评论(0编辑  收藏  举报