其实就是以另外一种方式给出了一棵二叉树,然后要求根和左儿子和右儿子三者互相之间颜色互不相同,
比较好设计状态,
f【i】【0】 ,f【i】【1】,f【i】【2】分别表示根是绿红蓝三种颜色时的最多/最少绿色的数量,转移的时候只要保证上面的约束就行,并不难
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=500005;
const int inf=0x3f3f3f3f;
int f[N][3],ch[N][2];
int n,tot,rt;
char s[N+10];
int build()
{
tot++;
int id=tot;
if (s[id]=='0') return id;
if (s[id]=='1')
{
ch[id][0]=build();
return id;
}
else
{
ch[id][0]=build();
ch[id][1]=build();
return id;
}
}
void dfsmx(int u)
{
if (u==0) return ;
int l=ch[u][0],r=ch[u][1];
dfsmx(l);
dfsmx(r);
f[u][0]=max(f[l][1]+f[r][2],f[l][2]+f[r][1])+1;
f[u][1]=max(f[l][0]+f[r][2],f[l][2]+f[r][0]);
f[u][2]=max(f[l][0]+f[r][1],f[l][1]+f[r][0]);
}
void dfsmi(int u)
{
if (u==0) return ;
int l=ch[u][0],r=ch[u][1];
dfsmi(l);
dfsmi(r);
f[u][0]=min(f[l][1]+f[r][2],f[l][2]+f[r][1])+1;
f[u][1]=min(f[l][0]+f[r][2],f[l][2]+f[r][0]);
f[u][2]=min(f[l][0]+f[r][1],f[l][1]+f[r][0]);
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
rt=build();
dfsmx(1);
printf("%d ",max(f[1][0],max(f[1][1],f[1][2])));
memset(f,0,sizeof(f));
dfsmi(1);
printf("%d",min(f[1][0],min(f[1][1],f[1][2])));
return 0;
}