以Splay树为基础,构建动态树,便于实现动态变化的树和森林
#include <bits/stdc++.h>
#define io cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define LL long long
#define ULL unsigned long long
#define EPS 1e-8
#define INF 0x7fffffff
#define SUB -INF - 1
using namespace std;
const int N = 300005;
struct node
{
int fa, ch[2], sum, val, lazy;
} t[N];
#define lc t[x].ch[0]
#define rc t[x].ch[1]
bool isRoot(int x)
{
int g = t[x].fa;
return t[g].ch[0] != x && t[g].ch[1] != x;
}
void pushup(int x)
{
t[x].sum = t[x].val ^ t[lc].sum ^ t[rc].sum;
}
void reverse(int x)
{
if (!x)
return;
swap(lc, rc);
t[x].lazy ^= 1;
}
void pushdown(int x)
{
if (t[x].lazy)
{
reverse(lc);
reverse(rc);
t[x].lazy = 0;
}
}
void push(int x)
{
if (!isRoot(x))
push(t[x].fa);
pushdown(x);
}
void rotate(int x)
{
int y = t[x].fa;
int z = t[y].fa;
int k = t[y].ch[1] == x;
if (!isRoot(y))
t[z].ch[t[z].ch[1] == y] = x;
t[x].fa = z;
t[y].ch[k] = t[x].ch[k ^ 1];
if (t[x].ch[k ^ 1])
t[t[x].ch[k ^ 1]].fa = y;
t[y].fa = x;
t[x].ch[k ^ 1] = y;
pushup(y);
}
void splay(int x)
{
int y, z;
push(x);
while (!isRoot(x))
{
y = t[x].fa, z = t[y].fa;
if (!isRoot(y))
(t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);
rotate(x);
}
pushup(x);
}
void access(int x)
{
for (int child = 0; x; child = x, x = t[x].fa)
{
splay(x);
rc = child;
pushup(x);
}
}
void makeroot(int x)
{
access(x);
splay(x);
reverse(x);
}
void split(int x, int y)
{
makeroot(x);
access(y);
splay(y);
}
void link(int x, int y)
{
makeroot(x);
t[x].fa = y;
}
void cut(int x, int y)
{
split(x, y);
if (t[y].ch[0] != x || rc)
return;
t[x].fa = t[y].ch[0] = 0;
pushup(x);
}
int findroot(int x)
{
access(x);
splay(x);
while (lc)
pushdown(x), x = lc;
return x;
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &t[i].val);
t[i].sum = t[i].val;
}
while (m--)
{
int opt, a, b;
scanf("%d%d%d", &opt, &a, &b);
switch (opt)
{
case 0:
split(a, b);
printf("%d\n", t[b].sum);
break;
case 1:
if (findroot(a) != findroot(b))
link(a, b);
break;
case 2:
cut(a, b);
break;
case 3:
splay(a);
t[a].val = b;
break;
}
}
return 0;
}