1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| #include <bits/stdc++.h> namespace IO { void input(int& x) { bool f; char c; for (f = 0; !isdigit(c = getchar());) if (c == '-') f = 1; for (x = 0; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ '0'); if (f) x = -x; } void output(int x, char c = '\n') { static char f[97]; int pf = 0; if (!x) return putchar('0'), putchar(c), void(); if (x < 0) x = -x, putchar('-'); while (x) f[pf++] = x % 10 + '0', x /= 10; while (pf) putchar(f[--pf]); putchar(c); } } using namespace IO; const int N = 1e6 + 7, INF = 1e9; namespace US { int dad[N], ans = 0; void init(int n) { for (int i = 1; i <= n; i++) dad[i] = i, ans ^= i; } int find(int x) { return x == dad[x] ? x : (dad[x] = find(dad[x])); } void merge(int c, int x, int y) { dad[c] = dad[x] = dad[y] = c, ans ^= c ^ x ^ y; } } namespace LCT { struct Node* null; struct Node { Node *pre, *son[2]; int vrt, sum; bool rev; bool get() const { return pre->son[1] == this; } bool isRoot() const { return pre->son[0] != this && pre->son[1] != this; } void connect(Node* x, bool id) { if (this != null) son[id] = x; if (x != null) x->pre = this; } void pushup() { sum = 1 + vrt + son[0]->sum + son[1]->sum; } void pushdown() { if (rev) { std::swap(son[0], son[1]); if (son[0] != null) son[0]->rev ^= 1; if (son[1] != null) son[1]->rev ^= 1; rev = 0; } } void rotate() { Node *y = pre, *z = y->pre; bool k = get(), kk = y->get(), t = y->isRoot(); y->connect(son[k ^ 1], k), connect(y, k ^ 1); if (t) pre = z; else z->connect(this, kk); y->pushup(), pushup(); } } pool[N], *tail; void splay(Node* x) { static Node* stk[N]; int pstk = 0; Node* y = stk[++pstk] = x; while (!x->isRoot()) stk[++pstk] = x = x->pre; while (pstk) stk[pstk--]->pushdown(); for (x = y; !x->isRoot(); x->rotate()) if (!(y = x->pre)->isRoot()) (x->get() == y->get() ? y : x)->rotate(); } void access(Node* x) { for (Node* y = null; x != null; x = (y = x)->pre) splay(x), x->vrt += x->son[1]->sum, x->connect(y, 1), x->vrt -= y->sum, x->pushup(); } void makeRoot(Node* x) { access(x), splay(x), x->rev ^= 1; } void init(int n) { *(null = pool) = {null, {null, null}, 0, 0, 0}, tail = pool + n; for (int i = 1; i <= n; i++) *(pool + i) = *null, (pool + i)->sum = 1; } void link(int u, int v) { Node *x = pool + u, *y = pool + v; makeRoot(x), makeRoot(y); y->pre = x, x->vrt += y->sum, x->pushup(); } int query(int u, int v) { Node *x = pool + u, *y = pool + v; makeRoot(y), access(x), splay(x); int all = x->sum / 2, lsum = 0, rsum = 0, rt = INT_MAX; while (x != null) { x->pushdown(); int lef = lsum + x->son[0]->sum, rig = rsum + x->son[1]->sum; if (std::max(lef, rig) <= all) rt = std::min(rt, int(x - pool)); if (lef < rig) lsum += 1 + x->vrt + x->son[0]->sum, x = x->son[1]; else rsum += 1 + x->vrt + x->son[1]->sum, x = x->son[0]; } return rt; } } int n, m; int main() { input(n), input(m), LCT::init(n), US::init(n); while (m--) { static char str[5]; int x, y; scanf("%s", str); if (*str == 'A') { input(x), input(y); int rtx = US::find(x), rty = US::find(y); LCT::link(x, y), US::merge(LCT::query(rtx, rty), rtx, rty); } else if (*str == 'Q') input(x), output(US::find(x)); else output(US::ans); } return 0; }
|