【题目链接】
【思路要点】
- 动态树模板题。
- 时间复杂度\(O(QLogN)\)。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 30005 template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } struct LinkCutTree { struct Node { int child[2]; int father, up; int value, sum; bool rev; } a[MAXN]; int size; void init() { size = 0; } void pushdown(int root) { if (a[root].rev) { swap(a[root].child[0], a[root].child[1]); if (a[root].child[0]) a[a[root].child[0]].rev ^= true; if (a[root].child[1]) a[a[root].child[1]].rev ^= true; a[root].rev = false; } } void update(int root) { a[root].sum = a[root].value; if (a[root].child[0]) a[root].sum += a[a[root].child[0]].sum; if (a[root].child[1]) a[root].sum += a[a[root].child[1]].sum; } bool get(int x) { pushdown(a[x].father); return x == a[a[x].father].child[1]; } void rotate(int x) { if (a[x].father == 0) return; int f = a[x].father, g = a[f].father; int tnp = get(f), tmp = get(x); pushdown(x); a[f].child[tmp] = a[x].child[tmp ^ 1]; a[a[x].child[tmp ^ 1]].father = f; a[x].child[tmp ^ 1] = f; a[f].father = x; if (g) a[g].child[tnp] = x; a[x].father = g; a[x].up = a[f].up; a[f].up = 0; update(f); update(x); } void splay(int x) { pushdown(x); for (int f = a[x].father; (f = a[x].father); rotate(x)) if (a[x].father) { if (get(f) == get(x)) rotate(f); else rotate(x); } } void make_tree(int value) { size++; a[size].value = value; a[size].sum = value; } void access(int x) { splay(x); int tmp = a[x].child[1]; a[tmp].father = 0; a[tmp].up = x; a[x].child[1] = 0; update(x); while (a[x].up) { int f = a[x].up; splay(f); tmp = a[f].child[1]; a[tmp].father = 0; a[tmp].up = f; a[f].child[1] = x; a[x].father = f; update(f); a[x].up = 0; splay(x); } } void reverse(int x) { access(x); splay(x); a[x].rev ^= true; } int find_root(int x) { access(x); splay(x); int ans = x; while (a[ans].child[0]) ans = a[ans].child[0]; splay(ans); return ans; } void modify(int x, int v) { access(x); splay(x); a[x].value = v; update(x); } void link(int x, int y) { reverse(x); access(x); access(y); splay(y); a[x].father = y; a[y].child[1] = x; update(y); } int query(int x, int y) { reverse(x); access(y); splay(y); return a[y].sum; } } LCT; int main() { int n; read(n); for (int i = 1; i <= n; i++) { int x; read(x); LCT.make_tree(x); } int m; read(m); for (int i = 1; i <= m; i++) { char opt[15]; int x, y; scanf("\n%s", opt); read(x), read(y); if (opt[0] == 'b') { if (LCT.find_root(x) == LCT.find_root(y)) printf("no\n"); else { printf("yes\n"); LCT.link(x, y); } } if (opt[0] == 'e') { if (LCT.find_root(x) != LCT.find_root(y)) printf("impossible\n"); else printf("%d\n", LCT.query(x, y)); } if (opt[0] == 'p') LCT.modify(x, y); } return 0; }