#include <cstdio>
#include <algorithm>
#define Get(x) (t[t[x].f].c[1] == x)
#define Nroot(x) (t[t[x].f].c[Get(x)] == x)
#define ls(x) t[x].c[0]
#define rs(x) t[x].c[1]
const int N = 1e5 + 5;
int read(int x = 0, int f = 1, char c = getchar()) {
for (; c < '0' || c > '9'; c = getchar())
if (c == '-') f = -1;
for (; c >='0' && c <='9'; c = getchar())
x = x * 10 + c - '0';
return x * f;
}
struct Tree {
int x, s, f, c[2];
bool tag;
}t[N];
int n, m;
void Pushup(int x) {
t[x].s = t[x].x ^ t[ls(x)].s ^ t[rs(x)].s;
}
void Rotate(int x) {
int y = t[x].f, z = t[y].f, s = Get(x);
if (Nroot(y)) t[z].c[Get(y)] = x; t[x].f = z;
t[y].c[s] = t[x].c[s^1]; t[t[x].c[s^1]].f = y;
t[x].c[s^1] = y; t[y].f = x;
Pushup(y); Pushup(x);
}
void Pushdown(int x) {
if (!t[x].tag) return;
t[x].tag = 0;
std::swap(ls(x), rs(x));
t[ls(x)].tag ^= 1, t[rs(x)].tag ^= 1;
}
void Update(int x) {
if (Nroot(x)) Update(t[x].f); Pushdown(x);
}
void Splay(int x) {
Update(x);
while (Nroot(x)) {
int y = t[x].f, z = t[y].f;
if (Nroot(y)) Get(x) == Get(y) ? Rotate(y) : Rotate(x);
Rotate(x);
}
}
void Access(int x) {
for (int y = 0; x; y = x, x = t[x].f)
Splay(x), t[x].c[1] = y, Pushup(x);
}
void Mroot(int x) {
Access(x); Splay(x); t[x].tag ^= 1;
}
int Froot(int x) {
Access(x); Splay(x);
while (t[x].c[0]) x = t[x].c[0];
return x;
}
void Split(int x, int y) {
Mroot(x); Access(y); Splay(y);
}
void Link(int x, int y) {
if (Froot(x) != Froot(y))
Mroot(x), t[x].f = y;
}
void Cut(int x, int y) {
if (Froot(x) != Froot(y)) return;
Split(x, y);
if (t[y].c[0] == x && !t[x].c[1]) t[x].f = t[y].c[0] = 0, Pushup(y);
}
int main() {
n = read(); m = read();
for (int i = 1; i <= n; ++i)
t[i].x = read();
while (m--) {
int od = read(), x = read(), y = read();
if (od == 0) Split(x, y), printf("%d\n", t[y].s);
else if (od == 1) Link(x, y);
else if (od == 2) Cut(x, y);
else if (od == 3) Access(x), Splay(x), t[x].x = y, Pushup(x);
}
return 0;
}
推荐 FlashHu的lct博客