hly1204's library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub hly1204/library

:heavy_check_mark: test/tree/dynamic_tree_vertex_add_path_sum.0.test.cpp

Depends on

Code

// competitive-verifier: PROBLEM https://judge.yosupo.jp/problem/dynamic_tree_vertex_add_path_sum

#include "node_pool.hpp"
#include "st_tree_node_base.hpp"
#include <iostream>

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n, q;
    std::cin >> n >> q;
    struct STTreeNode : STTreeNodeBase<STTreeNode> {
        long long Val, Sum;
        void do_update() {
            Sum = Val;
            if (left()) Sum += left()->Sum;
            if (right()) Sum += right()->Sum;
        }
    };
    FixedSizeNodePool<STTreeNode> pool(n);
    auto [node, id] = pool.get_func();
    for (int i = 0; i < n; ++i) {
        std::cin >> node(i)->Val;
        node(i)->update();
    }
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        std::cin >> u >> v;
        node(u)->link(node(v));
    }
    while (q--) {
        int cmd;
        std::cin >> cmd;
        if (cmd == 0) {
            int u, v, w, x;
            std::cin >> u >> v >> w >> x;
            node(u)->cut(node(v));
            node(w)->link(node(x));
        } else if (cmd == 1) {
            int p, x;
            std::cin >> p >> x;
            node(p)->expose();
            node(p)->Val += x;
            node(p)->update();
        } else {
            int u, v;
            std::cin >> u >> v;
            node(u)->evert();
            node(v)->expose();
            std::cout << node(v)->Sum << '\n';
        }
    }
    return 0;
}
#line 1 "test/tree/dynamic_tree_vertex_add_path_sum.0.test.cpp"
// competitive-verifier: PROBLEM https://judge.yosupo.jp/problem/dynamic_tree_vertex_add_path_sum

#line 2 "node_pool.hpp"

#include <list>
#include <memory>
#include <utility>
#include <vector>

template<typename NodeT> class FixedSizeNodePool {
    std::vector<NodeT> pool;

public:
    explicit FixedSizeNodePool(int n) : pool(n) {}
    NodeT *at(int ind) { return pool.data() + ind; }
    int id(NodeT *a) const { return a - pool.data(); }
    auto get_func() {
        return std::make_pair([this](int ind) { return at(ind); },
                              [this](NodeT *a) { return id(a); });
    }
};

template<typename NodeT> class DynamicSizeNodePool {
    struct Wrapped : public NodeT {
        using NodeT::NodeT;
        typename std::list<Wrapped>::iterator i;
    };
    std::list<Wrapped> used_list;
    std::list<Wrapped> free_list;

public:
    template<typename... Args> NodeT *make(Args &&...arg) {
        if (free_list.empty()) {
            auto &&node = used_list.emplace_back(std::forward<Args>(arg)...);
            node.i      = std::prev(used_list.end());
            return std::addressof(node);
        }
        used_list.splice(used_list.end(), free_list, std::prev(free_list.end()));
        auto &&node = used_list.back();
        node.~NodeT(); // i remains unchanged
        new (std::addressof(node)) NodeT(std::forward<Args>(arg)...);
        return std::addressof(node);
    }
    // this is lazy, if sth. relies on the order of dtor, do NOT use
    void retrieve(NodeT *node) {
        free_list.splice(free_list.end(), used_list, ((Wrapped *)node)->i);
    }
};
#line 2 "st_tree_node_base.hpp"

#line 4 "st_tree_node_base.hpp"

template<typename STTreeNodeT> class STTreeNodeBase {
    STTreeNodeBase *L;
    STTreeNodeBase *R;
    STTreeNodeBase *P;
    int Size;
    bool NeedFlip;

    enum class Child { LEFT, RIGHT };
    Child which() const { return P->L == this ? Child::LEFT : Child::RIGHT; }
    // has NO parent OR NOT a prefered child
    bool is_root() const { return P == nullptr || (P->L != this && P->R != this); }
    bool is_left_child() const { return which() == Child::LEFT; }
    bool is_right_child() const { return which() == Child::RIGHT; }

    // CRTP reimplement
    void do_flip() {}
    void do_propagate() {}
    void do_update() {}

protected:
    void base_flip() {
        NeedFlip = !NeedFlip;
        std::swap(L, R);
        ((STTreeNodeT &)*this).do_flip();
    }
    // base_propagate() is called to propagate the update information to child(ren).
    // There is no need to update the information combined from child(ren)
    // which should be done in base_update().
    void base_propagate() {
        ((STTreeNodeT &)*this).do_propagate();
        if (NeedFlip) {
            NeedFlip = false;
            if (L) L->base_flip();
            if (R) R->base_flip();
        }
    }
    // base_update() is called to update the information combined from child(ren).
    void base_update() {
        Size = 1;
        if (L) Size += L->Size;
        if (R) Size += R->Size;
        ((STTreeNodeT &)*this).do_update();
    }
    void base_rotate() {
        P->base_propagate();
        base_propagate();
        if (is_left_child()) {
            if ((P->L = R)) R->P = P;
            if (!P->is_root()) {
                if (P->is_left_child()) P->P->L = this;
                else { P->P->R = this; }
            }
            R = P, P = P->P, R->P = this;
            R->base_update();
        } else {
            if ((P->R = L)) L->P = P;
            if (!P->is_root()) {
                if (P->is_left_child()) P->P->L = this;
                else { P->P->R = this; }
            }
            L = P, P = P->P, L->P = this;
            L->base_update();
        }
    }
    void base_splay() {
        for (base_propagate(); !is_root(); base_rotate()) {
            if (!P->is_root()) {
                P->P->base_propagate();
                P->which() == which() ? P->base_rotate() : base_rotate();
            }
        }
        base_update();
    }

    STTreeNodeBase() : L(), R(), P(), Size(1), NeedFlip() {}

public:
    int size() const { return Size; }

    STTreeNodeT *left() const { return (STTreeNodeT *)L; }
    STTreeNodeT *right() const { return (STTreeNodeT *)R; }

    void update() { base_update(); }

    STTreeNodeT *expose() {
        STTreeNodeBase *a = this, *lca = a;
        base_splay();
        a->R = nullptr;
        while (a->P) {
            lca = a->P;
            lca->base_splay();
            a->P->R = a;
            a->base_rotate();
        }
        a->base_update();
        // now a is the root of the aux. tree
        return (STTreeNodeT *)lca;
    }
    void evert() { expose(), base_flip(); }
    STTreeNodeT *root() {
        expose();
        STTreeNodeBase *a = this;
        while (a->L) a = a->L;
        a->base_splay();
        return (STTreeNodeT *)a;
    }
    STTreeNodeT *parent() {
        expose();
        if (!L) return nullptr;
        STTreeNodeBase *a = L;
        a->base_propagate();
        while (a->R) {
            a = a->R;
            a->base_propagate();
        }
        a->base_splay();
        return (STTreeNodeT *)a;
    }
    // this op. WILL change the root
    void link(STTreeNodeT *a) {
        evert();
        if (a->root() != (STTreeNodeT *)this) P = a;
    }
    // this op. will NOT change the root
    void cut() {
        expose();
        STTreeNodeBase *b = L;
        L                 = nullptr;
        if (b) b->P = nullptr;
        base_update();
    }
    // this op. will NOT change the root
    void cut(STTreeNodeT *b) {
        if (parent() == b) {
            cut();
        } else if (b->parent() == (STTreeNodeT *)this) {
            b->cut();
        }
    }
    STTreeNodeT *select(int k) {
        // example: A --> B --> C --> D, where D is the root of the path
        // We use expose(A) than:
        // * size(A) = 4
        // * select(A, 0) returns D
        // * select(A, 1) returns C
        // * ...
        STTreeNodeBase *a = this;
        a->base_propagate();
        while ((a->L ? a->L->Size : 0) != k) {
            if ((a->L ? a->L->Size : 0) < k) {
                k -= (a->L ? a->L->Size : 0) + 1;
                a = a->R;
            } else {
                a = a->L;
            }
            a->base_propagate();
        }
        a->base_splay();
        return (STTreeNodeT *)a;
    }
    STTreeNodeT *jump(int k) { return select(Size - k - 1); }
};
#line 5 "test/tree/dynamic_tree_vertex_add_path_sum.0.test.cpp"
#include <iostream>

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n, q;
    std::cin >> n >> q;
    struct STTreeNode : STTreeNodeBase<STTreeNode> {
        long long Val, Sum;
        void do_update() {
            Sum = Val;
            if (left()) Sum += left()->Sum;
            if (right()) Sum += right()->Sum;
        }
    };
    FixedSizeNodePool<STTreeNode> pool(n);
    auto [node, id] = pool.get_func();
    for (int i = 0; i < n; ++i) {
        std::cin >> node(i)->Val;
        node(i)->update();
    }
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        std::cin >> u >> v;
        node(u)->link(node(v));
    }
    while (q--) {
        int cmd;
        std::cin >> cmd;
        if (cmd == 0) {
            int u, v, w, x;
            std::cin >> u >> v >> w >> x;
            node(u)->cut(node(v));
            node(w)->link(node(x));
        } else if (cmd == 1) {
            int p, x;
            std::cin >> p >> x;
            node(p)->expose();
            node(p)->Val += x;
            node(p)->update();
        } else {
            int u, v;
            std::cin >> u >> v;
            node(u)->evert();
            node(v)->expose();
            std::cout << node(v)->Sum << '\n';
        }
    }
    return 0;
}

Test cases

Env Name Status Elapsed Memory
clang++ almost_line_00 :heavy_check_mark: AC 662 ms 31 MB
clang++ almost_line_01 :heavy_check_mark: AC 658 ms 32 MB
clang++ example_00 :heavy_check_mark: AC 9 ms 22 MB
clang++ issue_1216_00 :heavy_check_mark: AC 121 ms 31 MB
clang++ max_random_00 :heavy_check_mark: AC 596 ms 33 MB
clang++ max_random_01 :heavy_check_mark: AC 564 ms 30 MB
clang++ max_random_02 :heavy_check_mark: AC 577 ms 33 MB
clang++ random_00 :heavy_check_mark: AC 369 ms 29 MB
clang++ random_01 :heavy_check_mark: AC 419 ms 28 MB
clang++ random_02 :heavy_check_mark: AC 229 ms 24 MB
clang++ random_03 :heavy_check_mark: AC 253 ms 31 MB
clang++ random_04 :heavy_check_mark: AC 146 ms 22 MB
clang++ small_00 :heavy_check_mark: AC 10 ms 20 MB
clang++ small_01 :heavy_check_mark: AC 9 ms 20 MB
clang++ small_02 :heavy_check_mark: AC 9 ms 21 MB
Back to top page