[lct] Luogu P2486 染色
题目描述
题解
- 就是道lct的模板题,每个点记录下该区间最左端的颜色,该区间最右端的颜色,和该区间的颜色段
- 区间合并的时候,判断一下该点的颜色与左儿子的区间最右端的颜色是否相同,还有右儿子的区间最左端的颜色
- 注意区间翻转的时候要将颜色也得翻转
代码
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 const int N=100010; 5 int n,m,ch[N][2],fa[N],tot[N],col[N],lcol[N],rcol[N],tag[N]; 6 bool rv[N]; 7 char s[10]; 8 void update(int x) 9 { 10 lcol[x]=ch[x][0]?lcol[ch[x][0]]:col[x],rcol[x]=ch[x][1]?rcol[ch[x][1]]:col[x]; 11 if (ch[x][0]&&ch[x][1]) tot[x]=tot[ch[x][0]]+tot[ch[x][1]]+1-(rcol[ch[x][0]]==col[x])-(lcol[ch[x][1]]==col[x]); 12 else if (ch[x][0]) tot[x]=tot[ch[x][0]]+(rcol[ch[x][0]]!=col[x]); else if (ch[x][1]) tot[x]=tot[ch[x][1]]+(lcol[ch[x][1]]!=col[x]); else tot[x]=1; 13 } 14 bool nroot(int x) { return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; } 15 void rev(int x) { if (x) rv[x]^=1,swap(ch[x][0],ch[x][1]),swap(lcol[x],rcol[x]); } 16 void change(int x,int y) { if (x) tag[x]=y,col[x]=lcol[x]=rcol[x]=y,tot[x]=1; } 17 void down(int x) 18 { 19 if (!nroot(x)) down(fa[x]); 20 if (rv[x]) rev(ch[x][0]),rev(ch[x][1]),rv[x]=0; 21 if (tag[x]) change(ch[x][0],tag[x]),change(ch[x][1],tag[x]),tag[x]=0; 22 } 23 void rotate(int x) 24 { 25 int y=fa[x],z=fa[y],o=x==ch[y][1]; 26 if (!nroot(y)) ch[z][y==ch[z][1]]=x; 27 fa[x]=z,ch[y][o]=ch[x][!o],fa[ch[x][!o]]=y,fa[y]=x,ch[x][!o]=y,update(y); 28 } 29 void splay(int x) 30 { 31 down(x); 32 for (int y=fa[x],z=fa[y];!nroot(x);rotate(x),y=fa[x],z=fa[y]) if (!nroot(y)) rotate(((ch[y][0]==x)^(ch[z][0]==y))?x:y); 33 update(x); 34 } 35 void access(int x) { for (int y=0;x;x=fa[y=x]) splay(x),ch[x][1]=y,update(x); } 36 void makeroot(int x) { access(x),splay(x),rev(x); } 37 void insert(int x,int y) { makeroot(x),fa[x]=y; } 38 void split(int x,int y) { makeroot(x),access(y),splay(y); } 39 int main() 40 { 41 freopen("data.in","r",stdin),scanf("%d%d",&n,&m); 42 for (int i=1;i<=n;i++) scanf("%d",&lcol[i]),rcol[i]=col[i]=lcol[i],tot[i]=1; 43 for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y); 44 for (int a,b,c;m;m--) 45 { 46 scanf("%s%d%d",s+1,&a,&b),split(a,b); 47 if (s[1]=='C') scanf("%d",&c),change(b,c); else printf("%d\n",tot[b]); 48 } 49 }