1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| #pragma GCC optimize(3) #include<bits/stdc++.h>
#define fa(x) tr[x].p #define lc(x) tr[x].s[0] #define rc(x) tr[x].s[1] #define notroot(x) lc(fa(x))==x||rc(fa(x))==x
const int N = 1e5+10; int n,m; struct node{ int s[2],p,v; int sum,tag; }tr[N]; /*不会改变虚实边*/ inline void pushup(int x){ tr[x].sum=tr[lc(x)].sum^tr[rc(x)].sum^tr[x].v; } inline void pushdown(int x){ if(tr[x].tag){ std::swap(lc(x),rc(x)); tr[lc(x)].tag^=1; tr[rc(x)].tag^=1; tr[x].tag=0; } }
inline void rotate(int x){ int y=fa(x),z=fa(y); int k=rc(y)==x; if(notroot(y)) tr[z].s[rc(z)==y]=x; fa(x)=z; tr[y].s[k]=tr[x].s[k^1]; fa(tr[x].s[k^1])=y; tr[x].s[k^1]=y; fa(y)=x; pushup(y),pushup(x); } inline void pushall(int x){//递归 先到树根 然后一层一层 pushdown if(notroot(x))pushall(fa(x)); pushdown(x); } inline void splay(int x){ pushall(x); while(notroot(x)){ int y=fa(x),z=fa(y); if(notroot(y)) (rc(y)==x)^(rc(z)==y)?rotate(x):rotate(y); rotate(x); } }
/*会改变虚实边*/ inline void access(int x){//x到根节点权变成实边// for(int y=0;x;){ splay(x); rc(x)=y; pushup(x); y=x,x=fa(x); } } inline void makeroot(int x){//原树中 x为原点 access(x);//打通路径 splay(x);//翻上来 tr[x].tag^=1;//旋转 }
inline void split(int x,int y){//将x y路径分离出来 makeroot(x);//将x变成树根 access(y);//给x于y通路 此时为啥不是直接是tr[x].sum 因为 通路之后 x不一定是平衡树的根节点 splay(y);//这里splay(x)splay(y)都可以 splay哪个就输出哪个 } inline int findroot(int x){//找树根 access(x); splay(x); while(lc(x)) pushdown(x),x=lc(x); splay(x); return x; } inline void link(int x,int y){//连接 makeroot(x);//先看看是不是在一颗树内 先把x变成树根 if(findroot(y)!=x)fa(x)=y;//找出y的根是不是x 不是就把树x加到y里 } inline void cut(int x,int y){ makeroot(x); if(findroot(y)==x&&fa(y)==x&&!lc(y)){ //首先判断x y是否在一个平衡树里 然后 x是y的节点 然后x是y的前一个(因为平衡树有边 并不代表原树有边) rc(x)=fa(y)=0; pushup(x); } }
signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(0); std::cin>>n>>m; for(int i=1;i<=n;i++) std::cin>>tr[i].v; while (m -- ){ int t,x,y; std::cin>>t>>x>>y; if(t==0){ split(x,y); std::cout<<tr[y].sum<<"\n"; } else if(t==1) link(x,y); else if(t==2) cut(x,y); else { splay(x); tr[x].v=y; pushup(x); } } }
|