[SDOI2011]染色

染色

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),

如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面n-1行每行包含两个整数x和y,表示x和y之间有一条无向边。

下面m行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

Sample Input

6 5

2 2 1 2 1 1

1 2

1 3

2 4

2 5

2 6

Q 3 5

C 2 1 1

Q 3 5

C 5 1 2

Q 3 5

Sample Output

3

1

2

思路:

树链剖分模板,存下一段中的左边界\(\And\)右边界\(\And\)出现段数

\(\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}\)

// #pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
# define read read1<int>()
# define Type template<typename T>
Type inline const T read1(){
    T m=0;
    char k=getchar();
    while(('0'>k||k>'9')&&(k!='-'))k=getchar();
    const bool f=(k=='-'?1:0);
    if(f)k=getchar();
    while('0'<=k&&k<='9')m=(m<<3)+(m<<1)+(k^48),k=getchar();
    return f?-m:m;
}
# define N 100001
int rk[N],dfn[N],f[N],son[N],siz[N],top[N],d[N],tot,va[N],s,b[N<<2];
class Tem{
    public:
        int lx,rx,h;
        Tem(int _=0,int __=0,int ___=0):lx(_),rx(__),h(___){};
        Tem& operator +=(Tem r){
            if(rx==r.lx)--h;
            rx=r.rx;h+=r.h;
            return *this;
        }
        Tem operator + (Tem r){return Tem(*this)+=r;}
        Tem operator ~ (){return Tem(rx,lx,h);}
}v[N<<2];
int Max(int a,int b){return a>b?a:b;}
struct E{int v,n;E(){}E(int a,int b):v(a),n(b){}}G[N<<1];
void add(int u,int v,int n){
	G[n]=E(v,b[u]);
	b[u]=n;
	G[--n]=E(u,b[v]);
	b[v]=n;
}
# define ls (d<<1)
# define rs (d<<1|1)
void pushup(int d){v[d]=v[ls]+v[rs];}
void build(int l,int r,int d){
	if(l==r)v[d].lx=v[d].rx=va[rk[l]],v[d].h=1;
	else{
		int mid=l+r>>1;
		build(l,mid,ls);build(mid+1,r,rs);
        pushup(d);
	}
}
Tem query(int l,int r,int tl,int tr,int d){
	if(l==tl&&tr==r)return v[d];
	int mid=tl+tr>>1;
    if(v[d].h==1)v[rs]=v[ls]=v[d];
	if(r<=mid)return query(l,r,tl,mid,d<<1);
	if(l>mid)return query(l,r,mid+1,tr,d<<1|1);
	return query(l,mid,tl,mid,d<<1)+query(mid+1,r,mid+1,tr,d<<1|1);
}
void cover(int l,int r,int v1,int d,int tl,int tr){
	if(l==tl&&r==tr)return (void)(v[d].lx=v[d].rx=v1,v[d].h=1);
	int mid=tl+tr>>1;
    if(v[d].h==1)v[rs]=v[ls]=v[d];
	if(r<=mid)cover(l,r,v1,ls,tl,mid);
	else if(l>mid)cover(l,r,v1,rs,mid+1,tr);
    else cover(l,mid,v1,ls,tl,mid),cover(mid+1,r,v1,rs,mid+1,tr);
    pushup(d);
}
void dfs1(int n,int fa){
	f[n]=fa;siz[n]=1;
	d[n]=d[fa]+1;son[n]=0;
	for(int i=b[n];i;i=G[i].n)
		if(G[i].v^fa){
			dfs1(G[i].v,n);
			siz[n]+=siz[G[i].v];
			if(siz[G[i].v]>siz[son[n]])
				son[n]=G[i].v;
		}
}
void dfs2(int n,int k){
	rk[dfn[n]=++tot]=n;
	top[n]=k;
	if(son[n])dfs2(son[n],k);
	for(int i=b[n];i;i=G[i].n)
		if(G[i].v^f[n]&&G[i].v^son[n])
			dfs2(G[i].v,G[i].v);
}
Tem inquiry(int u,int v){
	int tu=top[u],tv=top[v];
    Tem lans(0,0,0),rans(0,0,0);
    bool lfl=1,rfl=1;
	while(tu^tv)
		if(d[tu]>d[tv]){
            if(lfl)lans=~query(dfn[tu],dfn[u],1,s,1),lfl=0;
            else lans+=~query(dfn[tu],dfn[u],1,s,1);
			tu=top[u=f[tu]];
		}
		else{
            if(rfl)rans=query(dfn[tv],dfn[v],1,s,1),rfl=0;
			else rans=query(dfn[tv],dfn[v],1,s,1)+rans;
			tv=top[v=f[tv]];
		}
	if(d[u]>=d[v])
        if(rfl)rans=~query(dfn[v],dfn[u],1,s,1),rfl=0;
        else rans=~query(dfn[v],dfn[u],1,s,1)+rans;
	else if(lfl)lans=query(dfn[u],dfn[v],1,s,1),lfl=0;
        else lans+=query(dfn[u],dfn[v],1,s,1);
	return !lfl?!rfl?lans+rans:lans:rans;
}
void cover(int u,int v,int k)
{
	int tu=top[u],tv=top[v];
	while(tu^tv)
		if(d[tu]>d[tv])
		{
			cover(dfn[tu],dfn[u],k,1,1,s);
			tu=top[u=f[tu]];
		}
		else
		{
			cover(dfn[tv],dfn[v],k,1,1,s);
			tv=top[v=f[tv]];
		}
	if(d[u]>d[v])cover(dfn[v],dfn[u],k,1,1,s);
	else cover(dfn[u],dfn[v],k,1,1,s);
}
char str[3];
int main()
{
	for(int T=1;T--;){
		s=read;tot=0;int m=read;
        for(int i=1;i<=s;++i)va[i]=read;
		memset(b,0,sizeof(b));
		for(int i=1;i<s;++i)
			add(read,read,i<<1);
		dfs1(1,0);dfs2(1,1);
		build(1,s,1);
        while(m--){
            scanf("%s",str);
            int l=read,r=read;
            if(*str=='C')cover(l,r,read);
            else printf("%d\n",inquiry(l,r).h);
        }
	}
	return 0;
}
posted @ 2020-01-06 21:41  ファイナル  阅读(188)  评论(0)    收藏  举报