先放一篇很好的LCT总结:https://www.cnblogs.com/flashhu/p/8324551.html
看这个就够了,讲得非常好,在这里我就不多说了。
说几个要点,学会可以帮助更好的理解LCT:
1.若给出的是一棵有根树,那么就不能makeroot这种操作。
2.其次,若要找两个点的lca,我们可以access(x),再access(y),然后找x所在splay的父亲即可。特判在一条链上的情况
3.实际上LCT能维护的不过也就是子树信息,路径信息,子树信息可以看做是把一个点splay后去除左儿子的信息
4.路径信息就直接split(x,y),如果不支持换根或者不支持改变边的状态,考虑树上差分。
在今后刷LCT的时候遇到有趣的事情或者解法,会补blog。
体表粘一下xzy神的。(貌似前面一大片题都可以用树剖搞定,不过显然LCT代码又短,跑起来又快)
最后粘一粘模板:
#include
#define ls son[x][0]
#define rs son[x][1]
using namespace std;
const int N=100010;
int sum[N],val[N],son[N][2],fa[N],n,m,type,x,y;
int sta[N],top=0;
bool rev[N];
bool isroot(int x){
return son[fa[x]][0]!=x && son[fa[x]][1]!=x;
}
void pushdown(int x){
if(!rev[x]) return ;
rev[x]=false;
rev[ls]^=true;rev[rs]^=true;
swap(son[ls][0],son[ls][1]);
swap(son[rs][0],son[rs][1]);
}
void update(int x){
sum[x]=sum[ls]^sum[rs]^val[x];
}
void rotate(int x){
int f=fa[x],ff=fa[f],w=0;
if(son[f][0]==x) w=1;
else w=0;
if(!isroot(f)){
if(son[ff][0]==f) son[ff][0]=x;
else son[ff][1]=x;
}fa[x]=ff;
son[f][1-w]=son[x][w];
if(son[x][w]) fa[son[x][w]]=f;
fa[f]=x;son[x][w]=f;
update(f);update(x);
}
void splay(int x){
sta[top=1]=x;for(int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i];
for(int i=top;i>=1;i--) pushdown(sta[i]);
while(!isroot(x)){
if(!isroot(fa[x])){
if((son[fa[x]][0]==x) ^ (son[fa[fa[x]]][0]==fa[x])) rotate(x);
else rotate(fa[x]);
}
rotate(x);
}
}
void access(int x){
for(int last=0;x;last=x,x=fa[x]) splay(x),son[x][1]=last,update(x);
}
void makeroot(int x){
access(x);splay(x);rev[x]^=1;swap(son[x][0],son[x][1]);
}
int findroot(int x){
access(x);splay(x);
while(son[x][0]) pushdown(x),x=son[x][0];
return x;
}
void split(int x,int y){
makeroot(x);access(y);splay(y);
}
void link(int x,int y){
split(x,y);
if(findroot(y)==x) return ;
fa[x]=y;
}
void solve(int x,int y){
split(x,y);
printf("%d\n",sum[y]);
}
void cut(int x,int y){
split(x,y);
if(findroot(y)!=x || fa[x]!=y || son[x][1]) return ;
fa[x]=son[y][0]=0;
update(y);
}
void change(int x,int y){
access(x);splay(x);val[x]=y;update(x);
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&val[i]),sum[i]=val[i];
while(m--){
scanf("%d %d %d",&type,&x,&y);
if(type==0) solve(x,y);
if(type==1) link(x,y);
if(type==2) cut(x,y);
if(type==3) change(x,y);
}
}