BZOJ - 2243 染色 (LCT链修改+链查询)
同样是可以用LCT解决的树剖问题之一。
注意反转的时候要考虑对左右端点颜色的影响,而且要先反转再打标记(这点不知道为啥)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10; 5 int n,m,a[N],col[N][2],fa[N],ch[N][2],sum[N],flp[N],sta[N],tp,lz[N]; 6 #define ls(u) ch[u][0] 7 #define rs(u) ch[u][1] 8 int sf(int u) {return u==rs(fa[u]);} 9 bool isrt(int u) {return u!=ls(fa[u])&&u!=rs(fa[u]);} 10 void pu(int u) { 11 sum[u]=1,col[u][0]=col[u][1]=a[u]; 12 for(int f=0; f<2; ++f)if(ch[u][f]) { 13 sum[u]+=sum[ch[u][f]]; 14 col[u][f]=col[ch[u][f]][f]; 15 if(col[ch[u][f]][f^1]==a[u])--sum[u]; 16 } 17 } 18 void change(int u,int x) {if(u)a[u]=col[u][0]=col[u][1]=lz[u]=x,sum[u]=1;} 19 void rev(int u) {flp[u]^=1,swap(ls(u),rs(u)),swap(col[u][0],col[u][1]);} 20 void pd(int u) { 21 if(flp[u])rev(ls(u)),rev(rs(u)),flp[u]=0;; 22 if(~lz[u])change(ls(u),lz[u]),change(rs(u),lz[u]),lz[u]=-1; 23 } 24 void rot(int u) { 25 int v=fa[u],f=sf(u); 26 if(!isrt(v))ch[fa[v]][sf(v)]=u; 27 ch[v][f]=ch[u][f^1],fa[ch[v][f]]=v; 28 fa[u]=fa[v],ch[u][f^1]=v,fa[v]=u,pu(v); 29 } 30 void splay(int u) { 31 sta[tp=0]=u; 32 for(int v=u; !isrt(v); v=fa[v])sta[++tp]=fa[v]; 33 for(; ~tp; pd(sta[tp--])); 34 for(; !isrt(u); rot(u))if(!isrt(fa[u])&&sf(fa[u])==sf(u))rot(fa[u]); 35 pu(u); 36 } 37 void access(int u) {for(int v=0; u; splay(u),rs(u)=v,pu(u),u=fa[v=u]);} 38 void makert(int u) {access(u),splay(u),rev(u);} 39 void link(int u,int v) {makert(u),fa[u]=v;} 40 void split(int u,int v) {makert(u),access(v),splay(v);} 41 int main() { 42 scanf("%d%d",&n,&m); 43 for(int i=1; i<=n; ++i)scanf("%d",&a[i]),lz[i]=-1,pu(i); 44 for(int i=1; i<n; ++i) { 45 int u,v; 46 scanf("%d%d",&u,&v); 47 link(u,v); 48 } 49 while(m--) { 50 char ch; 51 int x,y,z; 52 scanf(" %c%d%d",&ch,&x,&y); 53 if(ch=='C')scanf("%d",&z),split(x,y),change(y,z); 54 else split(x,y),printf("%d\n",sum[y]); 55 } 56 return 0; 57 }