LCT裸题。
x到y的路径上的点是makeroot(x),access(y)后的splay上的所有节点。
注意很多个不保证。
#include<iostream> #include<cstring> #include<cstdio> #include<cstring> #define maxv 500500 using namespace std; int n,q,w[maxv],tree[maxv][5],fath[maxv],v[maxv],rev[maxv]; int type,x,y,stack[maxv],cnt; bool isroot(int x) { return (tree[fath[x]][1]!=x)&&(tree[fath[x]][2]!=x); } void pushdown(int x) { int ls=tree[x][1],rs=tree[x][2]; if (rev[x]) { rev[x]=0;rev[ls]^=1;rev[rs]^=1; swap(tree[x][1],tree[x][2]); } } void pushup(int x) { int ls=tree[x][1],rs=tree[x][2]; v[x]=v[ls]^v[rs]^w[x]; } void rotate(int x) { int y=fath[x],z=fath[y],l,r; if (tree[y][1]==x) l=1;else l=2; r=3-l; if (!isroot(y)) { if (tree[z][1]==y) tree[z][1]=x; else tree[z][2]=x; } fath[x]=z;fath[y]=x;fath[tree[x][r]]=y; tree[y][l]=tree[x][r];tree[x][r]=y; pushup(y);pushup(x); } void splay(int x) { cnt=0;stack[++cnt]=x; for(int i=x;!isroot(i);i=fath[i]) stack[++cnt]=fath[i]; for (int i=cnt;i>=1;i--) pushdown(stack[i]); while (!isroot(x)) { int y=fath[x],z=fath[y]; if (!isroot(y)) { if ((tree[y][1]==x)^(tree[z][1]==y)) rotate(x); else rotate(y); } rotate(x); } } void access(int x) { int regis=0; while (x) { splay(x); tree[x][2]=regis; regis=x;pushup(x);x=fath[x]; } } void makeroot(int x) { access(x); splay(x); rev[x]^=1; } void split(int x,int y) { makeroot(x);access(y);splay(y); printf("%d\n",v[y]); } int find(int x) { access(x); splay(x); int now=x; while (tree[now][1]) now=tree[now][1]; return now; } void link(int x,int y) { makeroot(x);fath[x]=y; } void cut(int x,int y) { makeroot(x);access(y); splay(y);tree[y][1]=0;fath[x]=0; } void work0() { scanf("%d%d",&x,&y); split(x,y); } void work1() { scanf("%d%d",&x,&y); if (find(x)!=find(y)) link(x,y); } void work2() { scanf("%d%d",&x,&y); if (find(x)==find(y)) cut(x,y); } void work3() { scanf("%d%d",&x,&y); access(x);splay(x);w[x]=y;pushup(x); } int main() { scanf("%d%d",&n,&q); for (int i=1;i<=n;i++) { scanf("%d",&w[i]); } for (int i=1;i<=q;i++) { scanf("%d",&type); if (type==0) work0(); else if (type==1) work1(); else if (type==2) work2(); else work3(); } return 0; }