LCT裸题,只是一开始rotate函数中吧fa[ch[u][d]]赋值成了u的爷爷,而不是父亲,wa了几发,结果一直以为是LCT哪里写错了,心塞。。。。还去网上学习了一发连通性。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#define ls(u) ch[u][0]
#define rs(u) ch[u][1]
#define maxn 300020
using namespace std;
int n,m,sum[maxn],ch[maxn][2],val[maxn],fa[maxn],flag[maxn],q[maxn],cnt;
inline int Q(int u){return u==rs(fa[u]);}
inline bool isrt(int u){return !fa[u]||(u!=rs(fa[u])&&u!=ls(fa[u]));}
inline void push_up(int u){sum[u]=sum[ls(u)]^sum[rs(u)]^val[u];}
inline void push_down(int u){
if(!flag[u])return;
swap(ls(u),rs(u));flag[u]=0;
if(ls(u))flag[ls(u)]^=1;
if(rs(u))flag[rs(u)]^=1;
}
void rotate(int u){
if(!u)return;
int d=!Q(u),f=fa[u],ff=fa[f];
if(!isrt(f))ch[ff][Q(f)]=u;fa[u]=ff;
if(ch[u][d])fa[ch[u][d]]=f;ch[f][!d]=ch[u][d];
fa[f]=u;ch[u][d]=f;
push_up(f);push_up(u);
}
void splay(int u){
if(!u)return;
int x;
for(x=q[cnt=1]=u;!isrt(x);x=fa[x])q[++cnt]=fa[x];
for(int i=cnt;i>=1;i--)push_down(q[i]);
while(!isrt(u)){
if(isrt(fa[u]))rotate(u);
else{
if(Q(fa[u])==Q(u))rotate(fa[u]);
else rotate(u);
rotate(u);
}
}
}
void access(int u){
for(int x=0;u;u=fa[x=u]){
splay(u);rs(u)=x;push_up(u);
}
}
int find(int u){
access(u);splay(u);
while(ls(u))u=ls(u);
return u;
}
void makert(int u){
access(u);splay(u);flag[u]^=1;
}
void cut(int u,int v){
makert(u);access(v);splay(v);
fa[u]=ls(v)=0;push_up(v);
}
void link(int u,int v){
makert(u);fa[u]=v;
}
void update(int u,int add){
splay(u);val[u]=add;push_up(u);
}
void query(int u,int v){
makert(u);access(v);splay(v);
printf("%d\n",sum[v]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",val+i),sum[i]=val[i];
int pos,x,y;
while(m--){
scanf("%d%d%d",&pos,&x,&y);
if(pos==0){
query(x,y);
}else if(pos==1){
if(find(x)!=find(y))link(x,y);
}else if(pos==2){
if(find(x)==find(y))cut(x,y);
}else if(pos==3)update(x,y);
}
return 0;
}