1864: [Zjoi2006]三色二叉树
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 647 Solved: 458
[ Submit][ Status][ Discuss]
Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
Sample Output
5 2
解题思路:先根据原序列构建出二叉树,然后在二叉树上进行树形DP。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char c[510000];
int size,tt;
int fa[510000];
int dui[2][510000];
int mi[4][510000],ma[4][510000];
void dfs(int fg,int o)
{
++size; fa[size]=fg; dui[o][fg]=size;
if (c[tt]=='0') return;
if (c[tt]=='1')
{
++tt;
dfs(size,0);
}else
{
int u=size;
++tt; dfs(u,0);
++tt; dfs(u,1);
}
}
void dp(int o)
{
if (dui[0][o]==0 && dui[1][o]==0)
{
mi[1][o]=0;mi[2][o]=0;mi[3][o]=1;ma[1][o]=0;ma[2][o]=0;ma[3][o]=1;
return;
}
if (dui[0][o]!=0) dp(dui[0][o]);
if (dui[1][o]!=0) dp(dui[1][o]);
if (dui[1][o]==0)
{
mi[1][o]=min(mi[2][dui[0][o]],mi[3][dui[0][o]]); mi[2][o]=min(mi[1][dui[0][o]],mi[3][dui[0][o]]); mi[3][o]=min(mi[1][dui[0][o]],mi[2][dui[0][o]])+1;
ma[1][o]=max(ma[2][dui[0][o]],ma[3][dui[0][o]]); ma[2][o]=max(ma[1][dui[0][o]],ma[3][dui[0][o]]); ma[3][o]=max(ma[1][dui[0][o]],ma[2][dui[0][o]])+1;
}else
{
mi[1][o]=min(mi[2][dui[0][o]]+mi[3][dui[1][o]],mi[3][dui[0][o]]+mi[2][dui[1][o]]);
mi[2][o]=min(mi[1][dui[0][o]]+mi[3][dui[1][o]],mi[3][dui[0][o]]+mi[1][dui[1][o]]);
mi[3][o]=min(mi[2][dui[0][o]]+mi[1][dui[1][o]],mi[1][dui[0][o]]+mi[2][dui[1][o]])+1;
ma[1][o]=max(ma[2][dui[0][o]]+ma[3][dui[1][o]],ma[3][dui[0][o]]+ma[2][dui[1][o]]);
ma[2][o]=max(ma[3][dui[0][o]]+ma[1][dui[1][o]],ma[1][dui[0][o]]+ma[3][dui[1][o]]);
ma[3][o]=max(ma[2][dui[0][o]]+ma[1][dui[1][o]],ma[1][dui[0][o]]+ma[2][dui[1][o]])+1;
}
}
int main()
{
scanf("%s",c+1);
tt=1; size=0;
dfs(0,0);
for (int i=1;i<=3;++i)
for (int j=1;j<=size;++j)
{
mi[i][j]=10000000; ma[i][j]-100000000;
}
dp(1);
long long ans1=max(max(ma[1][1],ma[2][1]),ma[3][1]);
long long ans2=min(min(mi[1][1],mi[2][1]),mi[3][1]);
printf("%lld %lld",ans1,ans2);
}