ZJOI2006 三色二叉树
首先 此题给出的时一个可以代表二叉树的一个序列
直接递归把树建出来就好了。
然后考虑DP。
比较容易想到的是一个f[i][3]的DP,分别代表以i为根时,i染三种颜色的最大数目。
直接根据限制转移即可,但代码比较长。
考虑(代码)简单一点的,
实际上,由于我们只在意绿色的染了多少,所以染其他两种色没有区别(也就是可以完全互相转换)。
所以考虑是否可以设f[i][2],分别代表以i为根时,i染或不染绿色的最大数目。
同样直接根据限制转移。
#include <bits/stdc++.h> #define LL long long using namespace std; const int MAXN=5e5+10; char Tr[MAXN]; int Id,Cnt,tot,head[MAXN],Son[MAXN][3],Min[MAXN][2],Max[MAXN][2]; void Build (int Nx) { Son[Nx][0]=Tr[++Cnt]-'0'; if (!Son[Nx][0]) return; for (int i=1;i<=Son[Nx][0];++i) { Son[Nx][i]=++Id; Build (Id); } } void Tr_DP (int Nx) { for (int i=1;i<=Son[Nx][0];++i) Tr_DP (Son[Nx][i]); if (Son[Nx][0]==0) { Min[Nx][1]=Max[Nx][1]=1; return; } else if (Son[Nx][0]==1) { int Nex=Son[Nx][1]; Min[Nx][1]+=Min[Nex][0]+1; Max[Nx][1]+=Max[Nex][0]+1; Min[Nx][0]=min (Min[Nex][0], Min[Nex][1]); Max[Nx][0]=max (Max[Nex][0], Max[Nex][1]); } else { int Nex1=Son[Nx][1], Nex2=Son[Nx][2]; Min[Nx][1]+=Min[Nex1][0]+Min[Nex2][0]+1; Max[Nx][1]+=Max[Nex1][0]+Max[Nex2][0]+1; Min[Nx][0]=min (Min[Nex1][0]+Min[Nex2][1], Min[Nex1][1]+Min[Nex2][0]); Max[Nx][0]=max (Max[Nex1][0]+Max[Nex2][1], Max[Nex1][1]+Max[Nex2][0]); } } int main () { scanf ("%s", Tr+1); Build (++Id); Tr_DP (1); printf ("%d %d\n", max (Max[1][0], Max[1][1]), min (Min[1][0], Min[1][1]) ); return 0; }