[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 = '.';
	}
}
原文地址:https://www.cnblogs.com/dixiao/p/15076757.html