library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub tko919/library

:heavy_check_mark: Link-Cut Tree
(Graph/linkcut.hpp)

Verified with

Code

#pragma once

template <typename M, typename N, N (*f)(N, N)> struct LCT {
    struct Node {
        Node *lp = nullptr, *rp = nullptr, *par = nullptr;
        N val;
        M sum;
        int idx, sz = 1;
        bool rev = 0;
        Node() {}
        Node(int idx, N val) : idx(idx), val(val) {}
        void inverse() {
            swap(lp, rp);
            sum.inverse();
            rev ^= 1;
        }
        void eval() {
            if (rev) {
                if (lp)
                    lp->inverse();
                if (rp)
                    rp->inverse();
                rev = 0;
            }
        }
        void update() {
            sz = 1;
            if (lp)
                sz += lp->sz;
            if (rp)
                sz += rp->sz;
            sum.merge(val, lp ? lp->sum : M(), rp ? rp->sum : M());
        }
        bool is_root() {
            return !par || (par->lp != this && par->rp != this);
        }
        void rotate() {
            Node *pp, *p, *c;
            p = par, pp = p->par;
            if (p->lp == this) {
                c = rp;
                rp = p;
                p->lp = c;
            } else {
                c = lp;
                lp = p;
                p->rp = c;
            }
            if (pp) {
                if (pp->lp == p)
                    pp->lp = this;
                if (pp->rp == p)
                    pp->rp = this;
            }
            par = pp;
            p->par = this;
            if (c)
                c->par = p;
            p->update();
            update();
        }
        void splay() {
            eval();
            while (!is_root()) {
                Node *q = par;
                if (q->is_root()) {
                    q->eval();
                    eval();
                    if (q->lp == this)
                        rotate();
                    else
                        rotate();
                } else {
                    Node *r = q->par;
                    r->eval();
                    q->eval();
                    eval();
                    if (r->lp == q) {
                        if (q->lp == this) {
                            q->rotate();
                            rotate();
                        } else {
                            rotate();
                            rotate();
                        }
                    } else {
                        if (q->rp == this) {
                            q->rotate();
                            rotate();
                        } else {
                            rotate();
                            rotate();
                        }
                    }
                }
            }
        }
    };
    LCT() {}
    Node *make(int idx, N val) {
        return new Node(idx, val);
    }
    Node *expose(Node *v) {
        Node *pre = nullptr;
        for (Node *cur = v; cur; cur = cur->par) {
            cur->splay();
            if (cur->rp)
                cur->sum.add(cur->rp->sum);
            cur->rp = pre;
            if (cur->rp)
                cur->sum.sub(cur->rp->sum);
            cur->update();
            pre = cur;
        }
        v->splay();
        return pre;
    }
    void link(Node *c, Node *p) {
        evert(c);
        expose(p);
        c->par = p;
        p->rp = c;
        p->update();
    }
    void cut(Node *c, Node *p) {
        evert(p);
        expose(c);
        c->lp->par = nullptr;
        c->lp = nullptr;
        c->update();
    }
    void evert(Node *v) {
        expose(v);
        v->inverse();
        v->eval();
    }
    Node *lca(Node *u, Node *v) {
        expose(u);
        return expose(v);
    }
    Node *root(Node *v) {
        expose(v);
        while (v->lp)
            v->eval(), v = v->lp;
        return v;
    }
    void update(Node *v, N x) {
        expose(v);
        v->val = f(v->val, x);
        v->update();
    }
    M &query(Node *u, Node *v) { // root = u -> v
        evert(u);
        expose(v);
        return v->sum;
    }
};

/**
 * @brief Link-Cut Tree
 */
#line 2 "Graph/linkcut.hpp"

template <typename M, typename N, N (*f)(N, N)> struct LCT {
    struct Node {
        Node *lp = nullptr, *rp = nullptr, *par = nullptr;
        N val;
        M sum;
        int idx, sz = 1;
        bool rev = 0;
        Node() {}
        Node(int idx, N val) : idx(idx), val(val) {}
        void inverse() {
            swap(lp, rp);
            sum.inverse();
            rev ^= 1;
        }
        void eval() {
            if (rev) {
                if (lp)
                    lp->inverse();
                if (rp)
                    rp->inverse();
                rev = 0;
            }
        }
        void update() {
            sz = 1;
            if (lp)
                sz += lp->sz;
            if (rp)
                sz += rp->sz;
            sum.merge(val, lp ? lp->sum : M(), rp ? rp->sum : M());
        }
        bool is_root() {
            return !par || (par->lp != this && par->rp != this);
        }
        void rotate() {
            Node *pp, *p, *c;
            p = par, pp = p->par;
            if (p->lp == this) {
                c = rp;
                rp = p;
                p->lp = c;
            } else {
                c = lp;
                lp = p;
                p->rp = c;
            }
            if (pp) {
                if (pp->lp == p)
                    pp->lp = this;
                if (pp->rp == p)
                    pp->rp = this;
            }
            par = pp;
            p->par = this;
            if (c)
                c->par = p;
            p->update();
            update();
        }
        void splay() {
            eval();
            while (!is_root()) {
                Node *q = par;
                if (q->is_root()) {
                    q->eval();
                    eval();
                    if (q->lp == this)
                        rotate();
                    else
                        rotate();
                } else {
                    Node *r = q->par;
                    r->eval();
                    q->eval();
                    eval();
                    if (r->lp == q) {
                        if (q->lp == this) {
                            q->rotate();
                            rotate();
                        } else {
                            rotate();
                            rotate();
                        }
                    } else {
                        if (q->rp == this) {
                            q->rotate();
                            rotate();
                        } else {
                            rotate();
                            rotate();
                        }
                    }
                }
            }
        }
    };
    LCT() {}
    Node *make(int idx, N val) {
        return new Node(idx, val);
    }
    Node *expose(Node *v) {
        Node *pre = nullptr;
        for (Node *cur = v; cur; cur = cur->par) {
            cur->splay();
            if (cur->rp)
                cur->sum.add(cur->rp->sum);
            cur->rp = pre;
            if (cur->rp)
                cur->sum.sub(cur->rp->sum);
            cur->update();
            pre = cur;
        }
        v->splay();
        return pre;
    }
    void link(Node *c, Node *p) {
        evert(c);
        expose(p);
        c->par = p;
        p->rp = c;
        p->update();
    }
    void cut(Node *c, Node *p) {
        evert(p);
        expose(c);
        c->lp->par = nullptr;
        c->lp = nullptr;
        c->update();
    }
    void evert(Node *v) {
        expose(v);
        v->inverse();
        v->eval();
    }
    Node *lca(Node *u, Node *v) {
        expose(u);
        return expose(v);
    }
    Node *root(Node *v) {
        expose(v);
        while (v->lp)
            v->eval(), v = v->lp;
        return v;
    }
    void update(Node *v, N x) {
        expose(v);
        v->val = f(v->val, x);
        v->update();
    }
    M &query(Node *u, Node *v) { // root = u -> v
        evert(u);
        expose(v);
        return v->sum;
    }
};

/**
 * @brief Link-Cut Tree
 */
Back to top page