BZOJ 2243: [SDOI2011]染色(树剖||LCT)
题意:
给你一棵树,每个点有个颜色,有两个操作。
1 询问一条路径有多少段颜色。
2 将一条路径全部染成一个颜色。
题解:
这题可以用树剖+线段树维护。
但是LCT超级好写。
要注意的就是rev那里要把左右颜色也要换一换。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 #define mst(a,b) memset(a,b,sizeof(a)) 4 using namespace std; 5 6 namespace LCT 7 { 8 const int N=1e5+7; 9 int f[N],son[N][2],val[N],sum[N],tmp[N],lazy[N],lc[N],rc[N]; 10 int g[N],v[N*2],nxt[N*2],ed;bool rev[N]; 11 void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} 12 void build(int x=1){ 13 sum[x]=val[x]; 14 for(int i=g[x];i;i=nxt[i]) 15 if(!f[v[i]]&&v[i]!=1)f[v[i]]=x,build(v[i]); 16 } 17 bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;} 18 void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]),swap(lc[x],rc[x]);rev[x]^=1;} 19 void add(int x,int c){if(!x)return;sum[x]=1;val[x]=lazy[x]=lc[x]=rc[x]=c;} 20 void pb(int x){ 21 if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0; 22 if(lazy[x])add(son[x][0],lazy[x]),add(son[x][1],lazy[x]),lazy[x]=0; 23 } 24 void up(int x){ 25 sum[x]=1,lc[x]=rc[x]=val[x]; 26 if(son[x][0])sum[x]+=sum[son[x][0]]-(val[x]==rc[son[x][0]]),lc[x]=lc[son[x][0]]; 27 if(son[x][1])sum[x]+=sum[son[x][1]]-(val[x]==lc[son[x][1]]),rc[x]=rc[son[x][1]]; 28 } 29 void rotate(int x){ 30 int y=f[x],w=son[y][1]==x; 31 son[y][w]=son[x][w^1]; 32 if(son[x][w^1])f[son[x][w^1]]=y; 33 if(f[y]){ 34 int z=f[y]; 35 if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x; 36 } 37 f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y); 38 } 39 void splay(int x){ 40 int s=1,i=x,y;tmp[1]=i; 41 while(!isroot(i))tmp[++s]=i=f[i]; 42 while(s)pb(tmp[s--]); 43 while(!isroot(x)){ 44 y=f[x]; 45 if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);} 46 rotate(x); 47 } 48 up(x); 49 } 50 void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);} 51 int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;} 52 void makeroot(int x){access(x);splay(x);rev1(x);} 53 void link(int x,int y){makeroot(x);f[x]=y;access(x);} 54 void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);} 55 void cut(int x,int y){makeroot(x);cutf(y);} 56 void update(int x,int y,int c){makeroot(x),access(y),splay(y),add(y,c);} 57 int ask(int x,int y){makeroot(x);access(y);splay(y);return sum[y];} 58 } 59 60 using namespace LCT; 61 int n,m,x,y,c; 62 char op[3]; 63 64 int main() 65 { 66 scanf("%d%d",&n,&m); 67 F(i,1,n)scanf("%d",val+i),val[i]++; 68 F(i,2,n) 69 { 70 scanf("%d%d",&x,&y); 71 adg(x,y),adg(y,x); 72 } 73 build(); 74 F(i,1,m) 75 { 76 scanf("%s",op); 77 if(*op=='Q') 78 { 79 scanf("%d%d",&x,&y); 80 printf("%d\n",ask(x,y)); 81 } 82 else if(*op=='C') 83 { 84 scanf("%d%d%d",&x,&y,&c);c++; 85 update(x,y,c); 86 } 87 } 88 return 0; 89 }