动态树模板
Link Cut Tree:
#include<bits/stdc++.h> #define L(x) T[(x)].son[0] #define R(x) T[(x)].son[1] #define fa(x) T[(x)].fa using namespace std; const int N=300050; int stk[N]; int n,m; struct Tree{ int son[2],fa; int val,siz,Xor; bool tag; }T[N]; bool isroot(int x){ return (L(fa(x))==x||R(fa(x))==x)==0; } void pushup(int x){ T[x].Xor=T[L(x)].Xor^T[R(x)].Xor^T[x].val; return; } void rev(int x){ swap(L(x),R(x)); T[x].tag^=1; } void pushdown(int x){ if(T[x].tag){ if(L(x))rev(L(x)); if(R(x))rev(R(x)); T[x].tag=0; } } bool identify(int x){ return L(fa(x))==x?0:1; } void connect(int x,int fa,int son){ fa(x)=fa; T[fa].son[son]=x; } //以下Splay与普通的Splay有若干处不同 void rotate(int x){ int y=fa(x); int z=fa(y); int zson=identify(y); int yson=identify(x); int xson=T[x].son[yson^1]; fa(x)=fa(y);//将x的父亲设成y的父亲:区别1 if(!isroot(y))connect(x,z,zson);//判y,转的顺序不同:区别2 connect(xson,y,yson); connect(y,x,yson^1); pushup(y); pushup(x); return ; } void splay(int x){//传一个参:区别3 int tp=0,y=x; stk[++tp]=y; while(!isroot(y))stk[++tp]=y=fa(y); while(tp)pushdown(stk[tp--]);//存路径推标记:区别4 while(!isroot(x)){ int fa=fa(x); if(!isroot(fa)){//判y:区别5 if(identify(x)!=identify(fa)){ rotate(x); }else{ rotate(fa); } } rotate(x); }//无换根:区别6 } void access(int x){ for(int y=0;x;y=x,x=fa(x)){ splay(x); R(x)=y; pushup(x); } } void makeroot(int x){ access(x); splay(x); rev(x); } int findroot(int x){ access(x); splay(x); while(L(x)){ pushdown(x); x=L(x); } splay(x); return x; } void split(int x,int y){ makeroot(x); access(y); splay(y); } void link(int x,int y){ makeroot(x); if(findroot(y)==x)return; fa(x)=y; } void cut(int x,int y){ makeroot(x); if(findroot(y)!=x||fa(y)!=x||L(y))return; fa(y)=R(x)=0; pushup(x); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&T[i].val); } for(int i=1;i<=m;i++){ int opt,x,y; scanf("%d%d%d",&opt,&x,&y); if(opt==0){ split(x,y); printf("%d\n",T[y].Xor); }else if(opt==1){ link(x,y); }else if(opt==2){ cut(x,y); }else if(opt==3){ splay(x); T[x].val=y; } } }
其他动态树待补