P2585 [ZJOI2006]三色二叉树
题目
难得自己独立想出来并一次过的题目!!!后来翻了下题解自己似乎写复杂了()
首先,染绿色这东西不用管,只要用三种颜色然后最后让最大或最小的那个颜色是绿色即可。
一看题,这递归建树挺 ex 的。定义 $f[0/1/2][x]$ 表示 $x$ 子树内的颜色 $0/1/2$ 的数量。转移了一下,发现不行。
再加一维,$f[0/1/2][0/1/2][x]$ 第一维表示 $x$ 点染的颜色,第二维表示统计 $x$ 子树内的哪种颜色。大力转移即可。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#define ll long long
using namespace std;
int rd() {
int f=1,sum=0; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
ll lrd() {
ll f=1,sum=0; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
#define int ll
#define max(A,B) (A>B?A:B)
#define min(A,B) (A>B?B:A)
const int N=(int)(5e5+5);
struct edge {
int nex,to;
}e[N<<1];
char str[N];
int head[N],cnt,tot,n,f[3][3][N]; //第一维它自己染什么颜色
void add_edge(int x,int y) {
e[++cnt].nex=head[x]; e[cnt].to=y; head[x]=cnt;
}
void init(int x) {
if(str[x]=='0'||x>n) return ;
if(str[x]=='2') {
int pre=tot;
add_edge(tot,tot+1),add_edge(tot+1,tot),++tot;
init(x+1); add_edge(pre,tot+1),add_edge(tot+1,pre),++tot;
init(x+tot-pre);
} else {
add_edge(tot,tot+1); add_edge(tot+1,tot); ++tot; init(x+1);
}
}
void dfs1(int x,int ff) {
int num=0; //cout<<x<<" "<<ff<<endl;
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].to; if(y==ff) continue;
dfs1(y,x); ++num;
}
if(!num) {
f[0][0][x]=f[1][1][x]=f[2][2][x]=1;
} else if(num==1) {
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].to; if(y==ff) continue;
f[0][0][x]+=1+max(f[1][0][y],f[2][0][y]);
f[0][1][x]+=max(f[1][1][y],f[2][1][y]);
f[0][2][x]+=max(f[1][2][y],f[2][2][y]);
f[1][0][x]+=max(f[0][0][y],f[2][0][y]);
f[1][1][x]+=1+max(f[0][1][y],f[2][1][y]);
f[1][2][x]+=max(f[0][2][y],f[2][2][y]);
f[2][0][x]+=max(f[0][0][y],f[1][0][y]);
f[2][1][x]+=max(f[0][1][y],f[1][1][y]);
f[2][2][x]+=1+max(f[0][2][y],f[1][2][y]);
}
} else {
int ls=0,rs;
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].to; if(y==ff) continue;
if(!ls) ls=y; else rs=y;
}
f[0][0][x]+=1+max(f[1][0][ls]+f[2][0][rs],f[1][0][rs]+f[2][0][ls]);
f[0][1][x]+=max(f[1][1][ls]+f[2][1][rs],f[1][1][rs]+f[2][1][ls]);
f[0][2][x]+=max(f[1][2][ls]+f[2][2][rs],f[1][2][rs]+f[2][2][ls]);
f[1][0][x]+=max(f[0][0][ls]+f[2][0][rs],f[0][0][rs]+f[2][0][ls]);
f[1][1][x]+=1+max(f[0][1][ls]+f[2][1][rs],f[0][1][rs]+f[2][1][ls]);
f[1][2][x]+=max(f[0][2][ls]+f[2][2][rs],f[0][2][rs]+f[2][2][ls]);
f[2][0][x]+=max(f[0][0][ls]+f[1][0][rs],f[0][0][rs]+f[1][0][ls]);
f[2][1][x]+=max(f[0][1][ls]+f[1][1][rs],f[0][1][rs]+f[1][1][ls]);
f[2][2][x]+=1+max(f[0][2][ls]+f[1][2][rs],f[0][2][rs]+f[1][2][ls]);
}
}
void dfs2(int x,int ff) {
int num=0; //cout<<x<<" "<<ff<<endl;
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].to; if(y==ff) continue;
dfs2(y,x); ++num;
}
if(!num) {
for(int i=0;i<3;i++) for(int j=0;j<3;j++) f[i][j][x]=0;
f[0][0][x]=f[1][1][x]=f[2][2][x]=1;
} else if(num==1) {
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].to; if(y==ff) continue;
f[0][0][x]+=1+min(f[1][0][y],f[2][0][y]);
f[0][1][x]+=min(f[1][1][y],f[2][1][y]);
f[0][2][x]+=min(f[1][2][y],f[2][2][y]);
f[1][0][x]+=min(f[0][0][y],f[2][0][y]);
f[1][1][x]+=1+min(f[0][1][y],f[2][1][y]);
f[1][2][x]+=min(f[0][2][y],f[2][2][y]);
f[2][0][x]+=min(f[0][0][y],f[1][0][y]);
f[2][1][x]+=min(f[0][1][y],f[1][1][y]);
f[2][2][x]+=1+min(f[0][2][y],f[1][2][y]);
}
} else {
int ls=0,rs;
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].to; if(y==ff) continue;
if(!ls) ls=y; else rs=y;
}
f[0][0][x]+=1+min(f[1][0][ls]+f[2][0][rs],f[1][0][rs]+f[2][0][ls]);
f[0][1][x]+=min(f[1][1][ls]+f[2][1][rs],f[1][1][rs]+f[2][1][ls]);
f[0][2][x]+=min(f[1][2][ls]+f[2][2][rs],f[1][2][rs]+f[2][2][ls]);
f[1][0][x]+=min(f[0][0][ls]+f[2][0][rs],f[0][0][rs]+f[2][0][ls]);
f[1][1][x]+=1+min(f[0][1][ls]+f[2][1][rs],f[0][1][rs]+f[2][1][ls]);
f[1][2][x]+=min(f[0][2][ls]+f[2][2][rs],f[0][2][rs]+f[2][2][ls]);
f[2][0][x]+=min(f[0][0][ls]+f[1][0][rs],f[0][0][rs]+f[1][0][ls]);
f[2][1][x]+=min(f[0][1][ls]+f[1][1][rs],f[0][1][rs]+f[1][1][ls]);
f[2][2][x]+=1+min(f[0][2][ls]+f[1][2][rs],f[0][2][rs]+f[1][2][ls]);
}
}
signed main() {
scanf("%s",str+1); n=strlen(str+1);
tot=1; init(1);
dfs1(1,0); int ans1=0,ans2=2e18; for(int i=0;i<3;i++) for(int j=0;j<3;j++) ans1=max(ans1,f[i][j][1]);
memset(f,0,sizeof(f));
dfs2(1,0); for(int i=0;i<3;i++) for(int j=0;j<3;j++) ans2=min(ans2,f[i][j][1]);
printf("%lld %lld",ans1,ans2); return 0;
}

浙公网安备 33010602011771号