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;
}

 

posted @ 2018-10-17 21:55  薄荷凉了夏  阅读(233)  评论(1编辑  收藏  举报