染色
给定一棵有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 5Sample 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; }
来源:https://www.cnblogs.com/SYDevil/p/12158663.html