1864: [Zjoi2006]三色二叉树

人畜无害的树形DP

感觉回到了NOIP(DP爆内存什么的不谈了,捂脸)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=500000+5;
const int inf=1e9;
int lc[N],rc[N],d[N][3],now;//0 green 1 blue 2 red 
int choose[3][2];
char ch[N];
bool vis[N][3];
void build(int &x){
	x=++now;
	switch(ch[now]-'0'){
		case 0:return;
		case 1:build(lc[x]);break;
		case 2:build(lc[x]);build(rc[x]);break;
	}
}
int dp(int x,int c){
	if(vis[x][c])return d[x][c];
	vis[x][c]=true;
	int tmp=(!c)?1:0;
	if(!lc[x])return d[x][c]=tmp;
	if(!rc[x])d[x][c]=min(dp(lc[x],choose[c][0]),dp(lc[x],choose[c][1]))+tmp;
	else d[x][c]=min(dp(lc[x],choose[c][0])+dp(rc[x],choose[c][1]),dp(lc[x],choose[c][1])+dp(rc[x],choose[c][0]))+tmp;
	return d[x][c];
}
int d_p(int x,int c){
	if(vis[x][c])return d[x][c];
	vis[x][c]=true;
	int tmp=(!c)?1:0;
	if(!lc[x])return d[x][c]=tmp;
	if(!rc[x])d[x][c]=max(d_p(lc[x],choose[c][0]),d_p(lc[x],choose[c][1]))+tmp;
	else d[x][c]=max(d_p(lc[x],choose[c][0])+d_p(rc[x],choose[c][1]),d_p(lc[x],choose[c][1])+d_p(rc[x],choose[c][0]))+tmp;
	return d[x][c];
}
int main(){
	scanf("%s",ch+1);
	int root;
	choose[0][0]=1;choose[0][1]=2;choose[1][0]=0;choose[1][1]=2;choose[2][0]=0;choose[2][1]=1;
	build(root);
	printf("%d ",max(d_p(root,0),min(d_p(root,1),d_p(root,2))));
	memset(vis,false,sizeof(vis));
	printf("%d",min(dp(root,0),min(dp(root,1),dp(root,2))));
	return 0;
}


你可能感兴趣的:(1864: [Zjoi2006]三色二叉树)