結果

問題 No.1038 TreeAddQuery
ユーザー suisensuisen
提出日時 2022-08-05 21:26:35
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 675 ms / 4,000 ms
コード長 8,713 bytes
コンパイル時間 1,412 ms
コンパイル使用メモリ 108,628 KB
実行使用メモリ 72,276 KB
最終ジャッジ日時 2023-10-13 21:50:48
合計ジャッジ時間 12,741 ms
ジャッジサーバーID
(参考情報)
judge11 / judge14
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,348 KB
testcase_01 AC 1 ms
4,348 KB
testcase_02 AC 2 ms
4,352 KB
testcase_03 AC 7 ms
4,348 KB
testcase_04 AC 8 ms
4,352 KB
testcase_05 AC 7 ms
4,388 KB
testcase_06 AC 7 ms
4,352 KB
testcase_07 AC 7 ms
4,352 KB
testcase_08 AC 399 ms
51,616 KB
testcase_09 AC 433 ms
51,824 KB
testcase_10 AC 420 ms
52,436 KB
testcase_11 AC 428 ms
51,948 KB
testcase_12 AC 461 ms
52,256 KB
testcase_13 AC 675 ms
72,276 KB
testcase_14 AC 545 ms
57,660 KB
testcase_15 AC 509 ms
54,572 KB
testcase_16 AC 499 ms
53,600 KB
testcase_17 AC 502 ms
53,676 KB
testcase_18 AC 196 ms
51,836 KB
testcase_19 AC 206 ms
51,612 KB
testcase_20 AC 199 ms
51,680 KB
testcase_21 AC 220 ms
50,908 KB
testcase_22 AC 234 ms
51,348 KB
testcase_23 AC 250 ms
50,672 KB
testcase_24 AC 276 ms
51,028 KB
testcase_25 AC 634 ms
71,664 KB
testcase_26 AC 443 ms
62,000 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <chrono>

#include <algorithm>
#include <array>
#include <cassert>
#include <deque>
#include <iostream>
#include <queue>
#include <utility>
#include <vector>

namespace suisen {
    namespace default_operator {
        template <typename T>
        auto zero() -> decltype(T { 0 }) { return T { 0 }; }
        template <typename T>
        auto one()  -> decltype(T { 1 }) { return T { 1 }; }
        template <typename T>
        auto add(const T &x, const T &y) -> decltype(x + y) { return x + y; }
        template <typename T>
        auto sub(const T &x, const T &y) -> decltype(x - y) { return x - y; }
        template <typename T>
        auto mul(const T &x, const T &y) -> decltype(x * y) { return x * y; }
        template <typename T>
        auto div(const T &x, const T &y) -> decltype(x / y) { return x / y; }
        template <typename T>
        auto mod(const T &x, const T &y) -> decltype(x % y) { return x % y; }
        template <typename T>
        auto neg(const T &x) -> decltype(-x) { return -x; }
        template <typename T>
        auto inv(const T &x) -> decltype(one<T>() / x)  { return one<T>() / x; }
    } // default_operator
    namespace default_operator_noref {
        template <typename T>
        auto zero() -> decltype(T { 0 }) { return T { 0 }; }
        template <typename T>
        auto one()  -> decltype(T { 1 }) { return T { 1 }; }
        template <typename T>
        auto add(T x, T y) -> decltype(x + y) { return x + y; }
        template <typename T>
        auto sub(T x, T y) -> decltype(x - y) { return x - y; }
        template <typename T>
        auto mul(T x, T y) -> decltype(x * y) { return x * y; }
        template <typename T>
        auto div(T x, T y) -> decltype(x / y) { return x / y; }
        template <typename T>
        auto mod(T x, T y) -> decltype(x % y) { return x % y; }
        template <typename T>
        auto neg(T x) -> decltype(-x) { return -x; }
        template <typename T>
        auto inv(T x) -> decltype(one<T>() / x)  { return one<T>() / x; }
    } // default_operator
} // namespace suisen

namespace suisen {
    template <typename T, T(*_add)(T, T) = default_operator_noref::add<T>, T(*_zero)() = default_operator_noref::zero<T>, T(*_neg)(T) = default_operator_noref::neg<T>>
    struct PointGetRangeContourAddOnTree {
        using value_type = T;
    private:
        struct InternalFenwickTree {
            InternalFenwickTree() = default;
            InternalFenwickTree(int n) : _n(n), _dat(_n + 1, _zero()) {}
            value_type get(int i) const {
                value_type res = _zero();
                for (++i; i; i -= i & -i) res = _add(res, _dat[i]);
                return res;
            }
            void add(int l, int r, const value_type& val) {
                l = std::max(0, l), r = std::min(r, _n);
                if (l < r) add(l, val), add(r, _neg(val));
            }
        private:
            int _n;
            std::vector<value_type> _dat;

            void add(int r, const value_type& val) {
                for (++r; r <= _n; r += r & -r) _dat[r] = _add(_dat[r], val);
            }
        };
        using sequence_type = InternalFenwickTree;

        struct AuxInfo {
            int child_index;
            int dist;
        };

        struct TreeNode {
            std::vector<int> adj;
            typename std::array<AuxInfo, 30>::iterator info_it;
        };
    public:
        PointGetRangeContourAddOnTree(int n = 0, const value_type& fill_value = _zero()) : PointGetRangeContourAddOnTree(std::vector<value_type>(n, fill_value)) {}
        PointGetRangeContourAddOnTree(const std::vector<value_type>& dat) : _n(dat.size()), _dat(dat), _nodes(_n), _par(_n, -1), _info(_n), _subtrees(_n), _trees(_n) {
            _par.reserve(2 * _n);
            _subtrees.reserve(2 * _n);
            for (int i = 0; i < _n; ++i) {
                _nodes[i].info_it = _info[i].begin();
            }
        }

        void add_edge(int u, int v) {
            _nodes[u].adj.push_back(v);
            _nodes[v].adj.push_back(u);
        }

        void build() {
            std::vector<int> sub_size(_n, 0);

            auto build_sequence = [this](int root, const int child_index) {
                std::deque<std::pair<int, int>> dq { { root, -1 } };
                int dist = -1, nxt = root;
                while (dq.size()) {
                    const auto [u, pu] = dq.front();
                    dq.pop_front();
                    if (u == nxt) ++dist, nxt = -1;
                    auto& node = _nodes[u];
                    if (child_index >= 0) *node.info_it++ = { child_index, dist };
                    for (int v : node.adj) if (v != pu) {
                        dq.emplace_back(v, u);
                        if (nxt < 0) nxt = v;
                    }
                }
                return sequence_type(dist + 1);
            };

            auto rec = [&](auto rec, int r, int siz) -> int {
                int c = -1;
                auto get_centroid = [&](auto get_centroid, int u, int p) -> void {
                    sub_size[u] = 1;
                    for (int v : _nodes[u].adj) if (v != p) {
                        get_centroid(get_centroid, v, u);
                        if (v == c) {
                            sub_size[u] = siz - sub_size[c];
                            break;
                        }
                        sub_size[u] += sub_size[v];
                    }
                    if (c < 0 and sub_size[u] * 2 > siz) c = u;
                };
                get_centroid(get_centroid, r, -1);

                const int ch_num = _nodes[c].adj.size();
                _subtrees[c].resize(ch_num);
                for (int i = 0; i < ch_num; ++i) {
                    const int v = _nodes[c].adj[i];
                    _nodes[v].adj.erase(std::find(_nodes[v].adj.begin(), _nodes[v].adj.end(), c));
                    _par[rec(rec, v, sub_size[v])] = c;
                    _subtrees[c][i] = build_sequence(v, i);
                }
                _trees[c] = build_sequence(c, -1);
                for (int v : _nodes[c].adj) _nodes[v].adj.push_back(c);
                return c;
            };
            rec(rec, 0, _n);
        }

        value_type get(int u) const {
            value_type res = _dat[u] + _trees[u].get(0);
            int v = _par[u];
            const auto it_end = _nodes[u].info_it;
            for (auto it = _info[u].begin(); it != it_end; ++it) {
                res = _add(res, _trees[v].get(it->dist + 1));
                res = _add(res, _subtrees[v][it->child_index].get(it->dist));
                v = _par[v];
            }
            return res;
        }
        void set(int u, const value_type& new_val) {
            add(u, _add(new_val, _neg(get(u))));
        }
        void add(int u, const value_type &val) {
            _nodes[u].dat = _add(_dat[u], val);
        }
        void add(int u, int dl, int dr, const value_type &val) {
            _trees[u].add(dl, dr, val);
            int v = _par[u];
            const auto it_end = _nodes[u].info_it;
            for (auto it = _info[u].begin(); it != it_end; ++it) {
                int ql = dl - it->dist - 1, qr = dr - it->dist - 1;
                _trees[v].add(ql, qr, val);
                _subtrees[v][it->child_index].add(ql - 1, qr - 1, _neg(val));
                v = _par[v];
            }
        }

    private:
        int _n;
        std::vector<value_type> _dat;
        std::vector<TreeNode> _nodes;
        std::vector<int> _par;
        std::vector<std::array<AuxInfo, 30>> _info;
        std::vector<std::vector<sequence_type>> _subtrees;
        std::vector<sequence_type> _trees;
    };
} // namespace suisen

int main() {
    auto beg_time = std::chrono::system_clock::now();

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, q;
    std::cin >> n >> q;

    suisen::PointGetRangeContourAddOnTree<long long> g(n);

    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        std::cin >> u >> v;
        --u, --v;
        g.add_edge(u, v);
    }
    g.build();

    auto mid_time = std::chrono::system_clock::now();
    std::cerr << "build time : " << std::chrono::duration_cast<std::chrono::milliseconds>(mid_time - beg_time).count() << std::endl;

    for (int i = 0; i < q; ++i) {
        int x, y, z;
        std::cin >> x >> y >> z;
        --x, ++y;
        std::cout << g.get(x) << '\n';
        g.add(x, 0, y, z);
    }

    auto end_time = std::chrono::system_clock::now();
    std::cerr << "query time : " << std::chrono::duration_cast<std::chrono::milliseconds>(end_time - mid_time).count() << std::endl;
    return 0;
}

0