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
",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 }
原文地址:https://www.cnblogs.com/wfj2048/p/7508860.html