• [SDOI2011\]染色


    [SDOI2011]染色

    考虑直接维护一个类。

    写merge。

    inline void merge(S &a,S b,S c){//b + c -> a
    	a.v = b.v + c.v;
    	if(b.li == 0){
    		a.li = c.li;
    		a.ri = c.ri;
    	}else{
    		if(c.li == 0){
    			a.li = b.li;
    			a.ri = b.ri;
    		}else{
    			a.li = b.li;
    			a.ri = c.ri;
    			a.v -= (b.ri == c.li);
    		}
    	}
    }
    
    

    随便上个树剖。

    然后考虑怎么计算答案。

    考虑把路径分成三部分\([u->lca)[lca,lca](lca,v]\)

    考虑到我们在树剖时从下往上维护的一个类。

    他的左端点是底部,右端点是顶部。所以要翻转一个类。

    写了1h左右,不是很难写。

    // Problem: P2486 [SDOI2011]染色
    // Contest: Luogu
    // URL: https://www.luogu.com.cn/problem/P2486
    // Memory Limit: 125 MB
    // Time Limit: 1000 ms
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define N 100005
    
    struct P{
    	int to,next;
    }e[N << 1];
    
    ll n,q;
    
    ll head[N],cnt;
    
    inline void add(int x,int y){
    	e[++cnt].to = y;
    	e[cnt].next = head[x];
    	head[x] = cnt;
    }
    
    //tree
    
    ll f[N],dep[N],top[N],dfncnt,dfn[N],inv[N],to[N],son[N],siz[N];
    
    ll w[N];
    
    inline void dfs(int u,int fa){
    	dep[u] = dep[fa] + 1;
    	f[u] = fa;
    	siz[u] = 1;
    	for(int i = head[u];i;i = e[i].next){
    		int v = e[i].to;
    		if(v == fa)
    		continue;
    		dfs(v,u);
    		siz[u] += siz[v];
    		if(siz[v] > siz[son[u]])
    		son[u] = v;
    	}
    }
    
    inline void dfs2(int u,int t){
    	top[u] = t;
    	dfn[u] = ++dfncnt;	
    	inv[dfncnt] = u;
    	if(son[u])dfs2(son[u],t);
    	for(int i = head[u];i;i = e[i].next){
    		int v = e[i].to;
    		if(v == f[u] || v == son[u])continue;
    		dfs2(v,v);
    	}	
    }
    
    inline ll get(int x,int y){
    	while(top[x] != top[y]){
    			if(dep[top[x]] < dep[top[y]]) std::swap(x,y);
    			x= f[top[x]];
    	}
    	if(dep[x] > dep[y])std::swap(x,y);
    	return x;
    }
    
    //tree-cut
    
    #define mid ((l + r) >> 1)
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    
    struct S{
    	int li,ri,v;
    	S(){li = ri = v = 0;}
    }t[N << 2];
    
    ll tag[N << 2];
    
    inline void merge(S &a,S b,S c){//b + c -> a
    	a.v = b.v + c.v;
    	if(b.li == 0){
    		a.li = c.li;
    		a.ri = c.ri;
    	}else{
    		if(c.li == 0){
    			a.li = b.li;
    			a.ri = b.ri;
    		}else{
    			a.li = b.li;
    			a.ri = c.ri;
    			a.v -= (b.ri == c.li);
    		}
    	}
    }
    
    inline void build(int u,int l,int r){
    	if(l == r){
    		t[u].v = 1;
    		t[u].li = t[u].ri = w[inv[l]];
    		return ;
    	}
    	build(ls(u),l,mid);
    	build(rs(u),mid + 1,r);
    	merge(t[u],t[ls(u)],t[rs(u)]);
    }
    
    inline void del(int u){
    	if(tag[u]){
    		t[u].li = t[u].ri = tag[u];
    		t[u].v = 1;
    		return;
    	}
    }
    
    inline void down(int u){
    	if(tag[u]){
    		tag[ls(u)] = tag[u];
    		tag[rs(u)] = tag[u];
    		del(ls(u));
    		del(rs(u));
    		tag[u] = 0;
    	}
    }
    
    inline void change(int u,int l,int r,int tl,int tr,int to){
    	if(tl <= l && r <= tr){
    		tag[u] = to;
    		del(u);
    		return;
    	}
    	down(u);
    	if(tl <= mid)
    	change(ls(u),l,mid,tl,tr,to);
    	if(tr > mid)
    	change(rs(u),mid + 1,r,tl,tr,to);
    	merge(t[u],t[ls(u)],t[rs(u)]);
    }
    
    inline S que(int u,int l,int r,int tl,int tr){
    	S k1,k2;
    	if(tr < tl)
    	return k1;	
    	if(tl <= l && r <= tr)
    	return t[u];
    	down(u);
    	if(tl <= mid)
    	k1 = que(ls(u),l,mid,tl,tr);
    	if(tr > mid)
    	k2 = que(rs(u),mid + 1,r,tl,tr);
    	S ans;
    	merge(ans,k1,k2);
    	return ans;
    }
    
    //seg
    
    inline void dfs3(int u,int l,int r){
    	if(l == r){
    		std::cout<<t[u].li<<" "<<t[u].ri<<" "<<t[u].v<<" "<<l<<" "<<r<<std::endl;
    		return ;
    	}
    	dfs3(ls(u),l,mid);
    	dfs3(rs(u),mid + 1,r);
    			std::cout<<t[u].li<<" "<<t[u].ri<<" "<<t[u].v<<" "<<l<<" "<<r<<std::endl;
    			return ;
    }
    
    int main(){
    	scanf("%lld%lld",&n,&q);
    	for(int i = 1;i <= n;++i){
    		scanf("%lld",&w[i]);
    	}
    	for(int i = 1;i < n;++i){
    		ll x,y;
    		scanf("%lld%lld",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	dfs(1,0);
    	dfs2(1,0);
    	build(1,1,n);
    	// for(int i = 1;i <= n;++i)
    	// std::cout<<son[i]<<" "<<dfn[i]<<std::endl;
    	// dfs3(1,1,n);	
    	while(q -- ){
    		char a;
    		while(a != 'Q' && a != 'C')
    		a = getchar();
    		if(a == 'Q'){
    			ll x,y;
    			scanf("%lld%lld",&x,&y);
    			ll lca = get(x,y);
    			// std::cout<<lca<<std::endl;
    			S ans;
    			S z;
    			while(top[x] != top[lca]){
    				merge(ans,z = que(1,1,n,dfn[top[x]],dfn[x]),ans);
    				// std::cout<<dfn[top[x]]<<" "<<dfn[x]<<std::endl;x = f[top[x]];
    				// std::cout<<z.li<<" "<<z.ri<<" "<<z.v<<"QWQ"<<std::endl;
    				// std::cout<<ans.li<<" "<<ans.ri<<" "<<ans.v<<std::endl;
    				x = f[top[x]];
    			}
    			merge(ans,que(1,1,n,dfn[lca] + 1,dfn[x]),ans);
    			// std::cout<<dfn[lca] + 1<<" "<<dfn[x]<<std::endl;
    			S ans2;
    			while(top[y] != top[lca]){
    				merge(ans2,que(1,1,n,dfn[top[y]],dfn[y]),ans2);
    				// std::cout<<dfn[top[y]]<<" "<<dfn[y]<<std::endl;
    				// std::cout<<ans2.li<<" "<<ans2.ri<<" "<<ans2.v<<std::endl;
    				y = f[top[y]];
    			}
    			merge(ans2,que(1,1,n,dfn[lca] + 1,dfn[y]),ans2);	
    			// std::cout<<dfn[lca] + 1<<" "<<dfn[y]<<std::endl;
    			// std::cout<<ans2.li<<" "<<ans2.ri<<" "<<ans2.v<<std::endl;
    			std::swap(ans.li,ans.ri);
    			merge(ans,ans,que(1,1,n,dfn[lca],dfn[lca]));
    			//std::cout<<ans.li<<" "<<ans.ri<<" "<<ans.v<<std::endl;
    			merge(ans,ans,ans2);
    			std::cout<<ans.v<<std::endl;	
    		}else{
    			ll x,y,z;
    			scanf("%lld%lld%lld",&x,&y,&z);
    			while(top[x] != top[y]){
    				if(dep[top[x]] < dep[top[y]])std::swap(x,y);
    				change(1,1,n,dfn[top[x]],dfn[x],z);
    				x = f[top[x]];
    			}
    			if(dep[x] > dep[y]) std::swap(x,y);
    			change(1,1,n,dfn[x],dfn[y],z);
    		}
    		a = '.';
    	}
    }
    
  • 相关阅读:
    少年中国说--正能量传播
    刚刚加入程序员的行列,希望通过博客的形式记录自己在这个领域的点点滴滴。同时分享自己的心得体会。
    java中的路径问题(getResourceAsStream/tomcat/maven/getContextpath)等各种路径问题
    java的jdbc
    maven的插件
    maven的仓库
    java9新特性
    java8新特性
    java的网络编程
    java的多线程juc
  • 原文地址:https://www.cnblogs.com/dixiao/p/15076757.html
Copyright © 2020-2023  润新知