还不会LCT的小伙伴可以看一下这篇博客:LCT总结
我初学动态树时就是看着那篇博客学的,写的很好!
那好 言归正传。
显然树上 x 到 y 的路径的问题都可以用LCT Access一下把路径剖离出来,那主要问题在于如何用Splay 来维护颜色呢?
上图(XP 灵魂画手)
对于Splay树的每一个节点,维护四个信息
c[x] : 节点本身的颜色
cL[x]: 节点对应子树最左端的颜色
cR[x]: 节点对应子树最右端的颜色
tot[x]: 节点对应子树区间的颜色段数
所以upDATA的时候就很显然啦~
1 void pUP(int x){
2 int lc=ch[x][0],rc=ch[x][1];
3
4 cL[x]= lc? cL[lc]:c[x];
5 cR[x]= rc? cR[rc]:c[x];
6
7 if(lc && rc) tot[x]=tot[lc]+tot[rc]+1-(cR[lc]==c[x])-(cL[rc]==c[x]);
8
9 if(lc &&!rc) tot[x]=tot[lc]+1-(cR[lc]==c[x]);
10
11 if(!lc&& rc) tot[x]=tot[rc]+1-(cL[rc]==c[x]);
12
13 if(!lc&&!rc) tot[x]=1;
14 }
其他部分就和平常的LCT没有什么区别了
哦 对,pushDOWN时要注意 区间翻转,cL和cR要一起翻
全代码~
1 #include<iostream>
2 #include<cstdio>
3 #include<cstdlib>
4 #include<cstring>
5 #include<algorithm>
6
7 #define For(i,a,b) for(register int i=a;i<=b;++i)
8 #define Dwn(i,a,b) for(register int i=a;i>=b;--i)
9 #define Pn putchar('
')
10 #define I inline
11 #define Re register
12
13 using namespace std;
14
15 const int N=1e5+5;
16
17 int ch[N][2],fa[N],c[N],cL[N],cR[N],tot[N],tag[N],st[N],top,tgC[N];
18 int n,m,x,y,z;
19 char opt;
20
21 I void read(int &v){
22 v=0;
23 char c=getchar();
24 while(c<'0'||c>'9')c=getchar();
25 while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar();
26 }
27 void write(int x){
28 if(x>9)write(x/10);
29 int xx=x%10;
30 putchar(xx+'0');
31 }
32 I bool NOrt(int x){
33 return ch[fa[x]][1]==x || ch[fa[x]][0]==x;
34 }
35 I void pTAG(int x){
36 swap(ch[x][0],ch[x][1]);
37 swap(cL[x],cR[x]);
38 tag[x]^=1;
39 }
40 I void pTGC(int x,int Col){
41 c[x]=cL[x]=cR[x]=Col;
42 tot[x]=1;
43 tgC[x]=Col;
44 }
45 I void pDOWN(int x){
46 if(tag[x]){
47 if(ch[x][0])pTAG(ch[x][0]);
48 if(ch[x][1])pTAG(ch[x][1]);
49 tag[x]^=1;
50 }
51 if(tgC[x]){
52 if(ch[x][0])pTGC(ch[x][0],tgC[x]);
53 if(ch[x][1])pTGC(ch[x][1],tgC[x]);
54 tgC[x]=0;
55 }
56 }
57 I void pUP(int x){
58 int lc=ch[x][0],rc=ch[x][1];
59
60 cL[x]= lc? cL[lc]:c[x];
61 cR[x]= rc? cR[rc]:c[x];
62
63 if(lc && rc) tot[x]=tot[lc]+tot[rc]+1-(cR[lc]==c[x])-(cL[rc]==c[x]);
64
65 if(lc &&!rc) tot[x]=tot[lc]+1-(cR[lc]==c[x]);
66
67 if(!lc&& rc) tot[x]=tot[rc]+1-(cL[rc]==c[x]);
68
69 if(!lc&&!rc) tot[x]=1;
70 }
71 I bool Wson(int x){
72 return ch[fa[x]][1]==x;
73 }
74 I void Rotate(int x){
75 int y=fa[x];
76 int z=fa[y];
77 int ws=Wson(x);
78 if(NOrt(y))ch[z][Wson(y)]=x;
79 fa[x]=z;
80
81 ch[y][ws]=ch[x][ws^1];
82 if(ch[x][ws^1])fa[ch[x][ws^1]]=y;
83
84 ch[x][ws^1]=y;
85 fa[y]=x;
86
87 pUP(y); pUP(x);
88 }
89 I void Splay(int x){
90 top=0; int now=x;
91 st[++top]=now;
92 while(NOrt(now))st[++top]=now=fa[now];
93 while(top) pDOWN(st[top--]);
94
95 while(NOrt(x)){
96 int y=fa[x];
97 if(NOrt(y)){
98 if(Wson(y)==Wson(x))Rotate(y);
99 else Rotate(x);
100 }
101 Rotate(x);
102 }
103 }
104 I void Access(int x){
105 int lst=0;
106 while(x){
107 Splay(x); ch[x][1]=lst; pUP(x);
108 lst=x; x=fa[x];
109 }
110 }
111 I void ChangeRt(int x){
112 Access(x); Splay(x); pTAG(x);
113 }
114 I void Link(int x,int y){
115 ChangeRt(x); fa[x]=y;
116 }
117 I void Split(int x,int y){
118 ChangeRt(x); Access(y); Splay(y);
119 }
120 int main(){
121 read(n); read(m);
122 For(i,1,n){
123 read(c[i]); tot[i]=1;
124 cL[i]=cR[i]=c[i];
125 };
126 For(i,1,n-1){
127 read(x); read(y);
128 Link(x,y);
129 }
130 For(i,1,m){
131 opt=getchar();
132 while(opt!='C'&&opt!='Q')opt=getchar();
133 if(opt=='C'){
134 read(x); read(y); read(z);
135 Split(x,y); pTGC(y,z);
136 }
137 if(opt=='Q'){
138 read(x); read(y);
139 Split(x,y);
140 write(tot[y]); Pn;
141 }
142 }
143 return 0;
144 }