[BZOJ]1864: [Zjoi2006]三色二叉树
题解:$ dp[x][0/1/2] $分别表示结点颜色为绿,蓝,红时子树里面的最大最小绿色点的个数 转移就直接儿子结点转移即可
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=5e5+10; const double eps=1e-8; #define ll long long using namespace std; struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int dp[MAXN][3]; int dp1[MAXN][3]; int ch[MAXN][2]; int tot,cnt; char str[MAXN]; void dfs1(int x){ if(str[tot]=='0'){ tot++; dp[x][0]=dp1[x][0]=1; return ; } else if(str[tot]=='1'){cnt++;ch[x][0]=cnt;tot++;dfs1(cnt);} else{ tot++; cnt++;ch[x][0]=cnt;dfs1(cnt); cnt++;ch[x][1]=cnt;dfs1(cnt); } } void dfs2(int x){ if(ch[x][0])dfs2(ch[x][0]); if(ch[x][1])dfs2(ch[x][1]); int t1=ch[x][0];int t2=ch[x][1]; dp[x][0]=max(dp[t1][1]+dp[t2][2],dp[t1][2]+dp[t2][1])+1; dp[x][1]=max(dp[t1][0]+dp[t2][2],dp[t1][2]+dp[t2][0]); dp[x][2]=max(dp[t1][0]+dp[t2][1],dp[t1][1]+dp[t2][0]); dp1[x][0]=min(dp1[t1][1]+dp1[t2][2],dp1[t1][2]+dp1[t2][1])+1; dp1[x][1]=min(dp1[t1][0]+dp1[t2][2],dp1[t1][2]+dp1[t2][0]); dp1[x][2]=min(dp1[t1][0]+dp1[t2][1],dp1[t1][1]+dp1[t2][0]); } int main(){ scanf("%s",str);tot=0;cnt=1; dfs1(1); dfs2(1); printf("%d %d\n",max(dp[1][0],max(dp[1][1],dp[1][2])),min(dp1[1][0],min(dp1[1][1],dp1[1][2]))); }
1864: [Zjoi2006]三色二叉树
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 1443 Solved: 1086
[Submit][Status][Discuss]
Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
1122002010
Sample Output
5 2