【题目链接】
【思路要点】
- LinkCutTree模板题。
- 时间复杂度\(O(MLogN)\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 3e5 + 5; template <typename T> void read(T &x) { int f = 1; x = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -f; for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; x *= f; } struct LinkCutTree { struct Node { int child[2]; int father, up; int sum, val; bool inv; } a[MAXN]; int root, size; void maketree(int val) { size++; a[size].val = val; a[size].sum = val; } void pushdown(int x) { if (a[x].inv) { swap(a[x].child[0], a[x].child[1]); if (a[x].child[0]) a[a[x].child[0]].inv ^= true; if (a[x].child[1]) a[a[x].child[1]].inv ^= true; a[x].inv = false; } } void update(int x) { a[x].sum = a[x].val; if (a[x].child[0]) a[x].sum ^= a[a[x].child[0]].sum; if (a[x].child[1]) a[x].sum ^= a[a[x].child[1]].sum; } bool get(int x) { return x == a[a[x].father].child[1]; } void rotate(int x) { int f = a[x].father, g = a[f].father; a[x].up = a[f].up; a[f].up = 0; pushdown(f); pushdown(x); bool tmp = get(x); a[f].child[tmp] = a[x].child[tmp ^ 1]; a[a[x].child[tmp ^ 1]].father = f; a[f].father = x; a[x].child[tmp ^ 1] = f; a[x].father = g; if (g) a[g].child[a[g].child[1] == f] = x; update(f); update(x); } void splay(int x) { pushdown(x); for (int f = a[x].father; (f = a[x].father); rotate(x)) if (a[f].father) { pushdown(a[f].father); pushdown(f); if (get(x) == get(f)) rotate(f); else rotate(x); } } void access(int x) { splay(x); int tmp = a[x].child[1]; if (tmp) { a[tmp].up = x; a[tmp].father = 0; } a[x].child[1] = 0; update(x); while (a[x].up) { int f = a[x].up; splay(f); int tmp = a[f].child[1]; if (tmp) { a[tmp].up = f; a[tmp].father = 0; } a[f].child[1] = x; a[x].father = f; a[x].up = 0; update(f); splay(x); } } void reverse(int x) { access(x); splay(x); a[x].inv ^= true; } int findroot(int x) { access(x); pushdown(x); while (a[x].child[0]) { x = a[x].child[0]; pushdown(x); } splay(x); return x; } void link(int x, int y) { if (findroot(x) == findroot(y)) return; access(x); reverse(y); a[x].child[1] = y; a[y].father = x; update(x); } int query(int x, int y) { reverse(x); access(y); splay(y); return a[y].sum; } void cut(int x, int y) { reverse(x); access(y); splay(x); if (a[x].child[1] == y && a[y].child[0] == 0) { a[x].child[1] = 0; a[y].father = 0; update(x); } } void modify(int x, int y) { access(x); splay(x); a[x].val = y; update(x); } } LCT; int main() { int n, m; read(n), read(m); for (int i = 1; i <= n; i++) { int x; read(x); LCT.maketree(x); } for (int i = 1; i <= m; i++) { int opt, x, y; read(opt), read(x), read(y); if (opt == 0) printf("%d\n", LCT.query(x, y)); if (opt == 1) LCT.link(x, y); if (opt == 2) LCT.cut(x, y); if (opt == 3) LCT.modify(x, y); } return 0; }