Link-Cut Tree模版

cpp
struct LCT {
    struct Node {
        int ch[2], fa, val, xor_sum;
        bool rev;
    };

    vector<Node> tr;

    LCT(int n) : tr(n + 1) {}

    bool is_root(int u) {
        return tr[tr[u].fa].ch[0] != u && tr[tr[u].fa].ch[1] != u;
    }

    bool which(int u) {
        return tr[tr[u].fa].ch[1] == u;
    }

    void pushup(int u) {
        tr[u].xor_sum = tr[tr[u].ch[0]].xor_sum ^ tr[tr[u].ch[1]].xor_sum ^ tr[u].val;
    }

    void pushrev(int u) {
        if (!u) return;
        swap(tr[u].ch[0], tr[u].ch[1]);
        tr[u].rev ^= 1;
    }

    void pushdown(int u) {
        if (tr[u].rev) {
            pushrev(tr[u].ch[0]);
            pushrev(tr[u].ch[1]);
            tr[u].rev = 0;
        }
    }

    void rotate(int u) {
        int f = tr[u].fa, g = tr[f].fa;
        bool k = which(u);
        if (!is_root(f)) tr[g].ch[which(f)] = u;
        tr[u].fa = g;
        tr[f].ch[k] = tr[u].ch[k ^ 1];
        if (tr[u].ch[k ^ 1]) tr[tr[u].ch[k ^ 1]].fa = f;
        tr[u].ch[k ^ 1] = f;
        tr[f].fa = u;
        pushup(f);
        pushup(u);
    }

    void splay(int u) {
        vector<int> stk;
        int x = u;
        stk.push_back(x);
        while (!is_root(x)) {
            x = tr[x].fa;
            stk.push_back(x);
        }
        while (!stk.empty()) {
            pushdown(stk.back());
            stk.pop_back();
        }
        while (!is_root(u)) {
            int f = tr[u].fa, g = tr[f].fa;
            if (!is_root(f)) (which(f) == which(u)) ? rotate(f) : rotate(u);
            rotate(u);
        }
    }

    void access(int u) {
        for (int c = 0; u; c = u, u = tr[u].fa) {
            splay(u);
            tr[u].ch[1] = c;
            pushup(u);
        }
    }

    void make_root(int u) {
        access(u);
        splay(u);
        pushrev(u);
    }

    int find_root(int u) {
        access(u);
        splay(u);
        while (tr[u].ch[0]) {
            pushdown(u);
            u = tr[u].ch[0];
        }
        splay(u);
        return u;
    }

    void link(int u, int v) {
        make_root(u);
        if (find_root(v) != u) tr[u].fa = v;
    }

    void cut(int u, int v) {
        make_root(u);
        if (find_root(v) == u && tr[v].fa == u && !tr[v].ch[0]) {
            tr[v].fa = tr[u].ch[1] = 0;
            pushup(u);
        }
    }

    // 查询 u-v 路径信息(这里以异或和为例,可按需替换 pushup 中的合并逻辑)
    int query(int u, int v) {
        make_root(u);
        access(v);
        splay(v);
        return tr[v].xor_sum;
    }

    void update(int u, int val) {
        splay(u);
        tr[u].val = val;
        pushup(u);
    }
};
exgcd与中国剩余定理模版
LCA倍增模版