[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 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/11333799.html