动态树:
首先要明白的是他不止一棵树,是有很多树所形成的森林11
所以这才有了所谓的连边和删边操作,他是在两棵树之间进行的。
然后对于某一棵树我们对他弄一个辅助树,这个辅助树又是由很多splay树构成的。
对于题目要求什么值我们就只需要在pushup中修改就好啦

#include <cstring>
#include <algorithm>
using namespace std;

#define N 100010
#define fa(x) tr[x].fa
#define lc(x) tr[x].ch[0]
#define rc(x) tr[x].ch[1]
#define notroot(x) lc(fa(x))==x||rc(fa(x))==x
int n,m;
struct node{ //splay的信息
  int ch[2],fa,v,sum;
  int tag; //翻转懒标记
}tr[N]; 

void pushup(int x){ //上传
  tr[x].sum=tr[lc(x)].sum^tr[x].v^tr[rc(x)].sum;
}
void pushdown(int x){ //下传
  if(tr[x].tag){
    swap(lc(x),rc(x));
    tr[lc(x)].tag^=1;
    tr[rc(x)].tag^=1;
    tr[x].tag=0;
  }
}
void pushall(int x){ //递归下传
  if(notroot(x)) pushall(fa(x));
  pushdown(x);
}
void rotate(int x){ //旋转x
  int y=fa(x),z=fa(y),k=rc(y)==x; //y的右儿是x
  if(notroot(y)) tr[z].ch[rc(z)==y]=x; fa(x)=z; //z的儿是x,x的父是z
  tr[y].ch[k]=tr[x].ch[k^1]; fa(tr[x].ch[k^1])=y; //y的儿是x的异儿,x的异儿的父是y
  tr[x].ch[k^1]=y; fa(y)=x; //x的异儿是y,y的父是x
  pushup(y); pushup(x); //自底向上pushup
}
void splay(int x){ //x伸展到根
  pushall(x); //递归下传
  while(notroot(x)){ //折线转xx,直线转yx
    int y=fa(x),z=fa(y);
    if(notroot(y)) (rc(y)==x)^(rc(z)==y)?rotate(x):rotate(y);
    rotate(x);
  }
}
void access(int x){ //打通x到树根的路
  for(int y=0; x;){
    splay(x); //x转到当前splay的根
    rc(x)=y;  //x的右儿指向下面splay的根
    pushup(x); //更新x的sum
    y=x,x=fa(x); //存x,x爬到上面的splay
  }
}
void makeroot(int x){ //换根
  access(x); //通路
  splay(x);  //伸展
  tr[x].tag^=1; //翻转懒标记
}
void split(int x,int y){ //分离x到y的路径
  makeroot(x); //x换根
  access(y); //y通路
  splay(y);  //y伸展
}
void output(int x,int y){ //输出
  split(x,y); //分离
  printf("%d\n",tr[y].sum);
}
int findroot(int x){ //找根
  access(x);
  splay(x);
  while(lc(x)) pushdown(x),x=lc(x);
  splay(x); //防止卡链
  return x;
}
void link(int x,int y){ //连边
  makeroot(x);
  if(findroot(y)!=x) fa(x)=y;
}
void cut(int x,int y){ //断边
  makeroot(x);
  if(findroot(y)==x&&fa(y)==x&&!lc(y))
    fa(y)=0, pushup(x);
}
void change(int x,int y){ //修改
  splay(x);
  tr[x].v=y;
  pushup(x);
}
int main(){
  scanf("%d%d",&n,&m); int t,x,y;
  for(int i=1; i<=n; i++)scanf("%d",&tr[i].v);
  while(m--){
    scanf("%d%d%d",&t,&x,&y);
    if(t==0) output(x,y);
    else if(t==1) link(x,y);
    else if(t==2) cut(x,y);
    else change(x,y);
  }
}```