zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    android音量知识总结
    android设置dialog透明度,黑暗度的方法
    获得图片资源总结
    Fragment使用案例
    activity主窗口与软键盘的交互模式
    AndroidManifest.xml中android:configChanges的简介
    2G,3G和4G网络类型了解
    安卓权限大全
    Spring
    多线程
  • 原文地址:https://www.cnblogs.com/xugangfan/p/15177092.html
Copyright © 2011-2022 走看看