Link Cut Tree (LCT) template code:
CPP
#include<bits/stdc++.h>
using namespace std;
#define ls(x) T[x].son[0]
#define rs(x) T[x].son[1]
#define fa(x) T[x].p
#define not_rt(x) ls(fa(x)) == x || rs(fa(x)) == x
const int N = 1e5 + 7;
struct node{
int son[2], p, sum, v;
bool tag;
}T[N];
int n, m, op, x, y;
void push_up(int k){
T[k].sum = T[ls(k)].sum ^ T[rs(k)].sum ^ T[k].v;
}
void push_down(int k){
if(!T[k].tag) return;
swap(ls(k), rs(k));
T[ls(k)].tag ^= 1;
T[rs(k)].tag ^= 1;
T[k].tag = 0;
}
void rotate(int k){
int p = fa(k), gp = fa(p);
bool op = rs(p) == k;
if(not_rt(p)) T[gp].son[rs(gp) == p] = k; // virtual father cannot point to son
fa(k) = gp, fa(p) = k;
T[p].son[op] = T[k].son[op ^ 1];
fa(T[k].son[op ^ 1]) = p;
T[k].son[op ^ 1] = p;
push_up(p), push_up(k);
}
void push_all(int k){
if(not_rt(k)) push_all(fa(k));
push_down(k);
}
void splay(int k){
push_all(k); // son left/right order must be correct in order to splay correctly
while(not_rt(k)){
int p = fa(k), gp = fa(p);
if(not_rt(p)){
if(ls(p) == k ^ ls(gp) == p) rotate(k);
else rotate(p);
}
rotate(k);
}
}
void access(int k){ // establish real edge all the way to root
for(int y = 0; k; ){
splay(k); // move current node to the root of the current splay tree
rs(k) = y;
// Two moves in one:
// 1. unbind the real edge that used to be at rs, so there are no nodes with depth greater than the initial k
// 2. connect the other previous nodes that is above the initial k to this node
push_up(k);
y = k, k = fa(k);
}
}
void make_rt(int k){
access(k);
splay(k);
T[k].tag ^= 1;
// the node k is moved to the root, but in the in-order travesal, it is still the deepest node
// thus, we need to mandatorily reorder the tree, so that the deepest node is shallowest, and vice versa
// (all the nodes left of k is shallower than k, right is deeper)
}
void split(int x, int y){
make_rt(x); // make x the root of every node
access(y); // let x and y be in the same splay tree
splay(y); // prevent possible tle
}
int find_rt(int k){
access(k);
splay(k);
while(ls(k)) // must include push_down!!!
push_down(k), k = ls(k);
splay(k);
return k;
}
void link(int x, int y){
make_rt(x);
if(find_rt(y) != x) fa(x) = y;
}
void cut(int x, int y){
make_rt(x);
if(find_rt(y) == x && fa(y) == x && !ls(y)){
// !ls(y) means there are no nodes that are stuck between the depth of x and y
rs(x) = fa(y) = 0;
push_up(x);
}
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i ++){
cin >> x;
T[i].v = T[i].sum = x;
}
while(m --){
cin >> op >> x >> y;
if(!op) split(x, y), cout << T[y].sum << endl;
if(op == 1) link(x, y);
if(op == 2) cut(x, y);
if(op == 3) splay(x), T[x].v = y, push_up(x); // must push_up!!!
}
return 0;
}