結果

問題 No.1197 モンスターショー
ユーザー MisterMister
提出日時 2020-11-04 07:59:40
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 562 ms / 3,000 ms
コード長 8,174 bytes
コンパイル時間 1,477 ms
コンパイル使用メモリ 114,264 KB
実行使用メモリ 25,216 KB
最終ジャッジ日時 2024-07-22 09:46:21
合計ジャッジ時間 12,837 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,944 KB
testcase_02 AC 2 ms
6,940 KB
testcase_03 AC 2 ms
6,940 KB
testcase_04 AC 1 ms
6,940 KB
testcase_05 AC 2 ms
6,940 KB
testcase_06 AC 2 ms
6,940 KB
testcase_07 AC 93 ms
21,888 KB
testcase_08 AC 173 ms
12,544 KB
testcase_09 AC 209 ms
19,840 KB
testcase_10 AC 312 ms
19,328 KB
testcase_11 AC 220 ms
8,448 KB
testcase_12 AC 180 ms
6,940 KB
testcase_13 AC 87 ms
13,440 KB
testcase_14 AC 330 ms
13,824 KB
testcase_15 AC 246 ms
8,320 KB
testcase_16 AC 334 ms
22,144 KB
testcase_17 AC 380 ms
22,400 KB
testcase_18 AC 151 ms
9,216 KB
testcase_19 AC 311 ms
19,328 KB
testcase_20 AC 64 ms
8,320 KB
testcase_21 AC 238 ms
6,944 KB
testcase_22 AC 23 ms
6,944 KB
testcase_23 AC 339 ms
14,464 KB
testcase_24 AC 249 ms
14,336 KB
testcase_25 AC 155 ms
11,264 KB
testcase_26 AC 318 ms
11,648 KB
testcase_27 AC 343 ms
20,864 KB
testcase_28 AC 262 ms
12,416 KB
testcase_29 AC 188 ms
14,080 KB
testcase_30 AC 142 ms
15,360 KB
testcase_31 AC 134 ms
12,928 KB
testcase_32 AC 150 ms
6,940 KB
testcase_33 AC 82 ms
11,264 KB
testcase_34 AC 562 ms
23,172 KB
testcase_35 AC 535 ms
23,188 KB
testcase_36 AC 546 ms
23,304 KB
testcase_37 AC 532 ms
23,296 KB
testcase_38 AC 532 ms
23,284 KB
testcase_39 AC 530 ms
23,296 KB
testcase_40 AC 310 ms
25,216 KB
testcase_41 AC 2 ms
6,940 KB
testcase_42 AC 2 ms
6,944 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <functional>

template <class Cost = int>
struct Edge {
    int src, dst;
    Cost cost;

    Edge() = default;
    Edge(int src, int dst, Cost cost = 1)
        : src(src), dst(dst), cost(cost){};

    bool operator<(const Edge<Cost>& e) const { return cost < e.cost; }
    bool operator>(const Edge<Cost>& e) const { return cost > e.cost; }
};

template <class Cost = int>
struct Graph : public std::vector<std::vector<Edge<Cost>>> {
    Graph(int n = 0) : std::vector<std::vector<Edge<Cost>>>(n) {}

    void span(bool direct, int src, int dst, Cost cost = 1) {
        (*this)[src].emplace_back(src, dst, cost);
        if (!direct) (*this)[dst].emplace_back(dst, src, cost);
    }
};

template <class Cost>
struct HeavyLightDecomposition {
    // indexing
    // v: a vertex in original graph
    // i: assigned label of a vertex

    Graph<Cost> graph;
    std::vector<int> id, vs;  // id: v -> i, vs: i -> v
    std::vector<int> par, sz, head, dep, out;
    // these are all v-indexed
    // in equals to id
    int time;

    explicit HeavyLightDecomposition(const Graph<Cost>& graph)
        : graph(graph),
          id(graph.size()),
          vs(graph.size()),
          par(graph.size()),
          sz(graph.size()),
          head(graph.size()),
          dep(graph.size()),
          out(graph.size()),
          time(0) {
        dfs_sz(0, -1, 0);
        head[0] = 0;
        dfs_hld(0, -1);
    }

    void dfs_sz(int v, int p, int d) {
        par[v] = p;
        sz[v] = 1;
        dep[v] = d;

        if (!graph[v].empty() && graph[v].front().dst == p) {
            std::swap(graph[v].front(), graph[v].back());
        }

        for (auto& e : graph[v]) {
            if (e.dst == p) continue;

            dfs_sz(e.dst, v, d + 1);
            sz[v] += sz[e.dst];

            // heavy edge first
            if (sz[graph[v].front().dst] < sz[e.dst]) {
                std::swap(graph[v].front(), e);
            }
        }
    }

    void dfs_hld(int v, int p) {
        id[v] = time++;
        vs[id[v]] = v;

        bool first = true;
        for (auto e : graph[v]) {
            if (e.dst == p) continue;

            head[e.dst] = (first ? head[v] : e.dst);
            first = false;
            dfs_hld(e.dst, v);
        }

        out[v] = time;
    }

    int lca(int u, int v) {
        while (true) {
            if (id[u] > id[v]) std::swap(u, v);
            if (head[u] == head[v]) return u;
            v = par[head[v]];
        }
    }

    int dist(int u, int v) {
        return dep[u] + dep[v] - dep[lca(u, v)] * 2;
    }

    std::vector<std::pair<int, int>> path(int u, int v, bool is_edge) {
        std::vector<std::pair<int, int>> segs;

        while (true) {
            if (id[u] > id[v]) std::swap(u, v);

            if (head[u] == head[v]) {
                // when edge path, the lca has to be excluded
                segs.emplace_back(id[u] + is_edge, id[v] + 1);
                return segs;
            }

            segs.emplace_back(id[head[v]], id[v] + 1);
            v = par[head[v]];
        }
    }

    std::pair<int, int> subtree(int v, bool is_edge) {
        // when edge path, the root has to be excluded
        return {id[v] + is_edge, out[v]};
    }
};

template <class T, class E>
struct LazySegmentTree {
    using DMerger = std::function<T(T, T)>;
    using OMerger = std::function<E(E, E)>;
    using Applier = std::function<T(T, E, int)>;

    int length;

    T d_unit;
    E o_unit;

    std::vector<T> dat;
    std::vector<E> ope;

    DMerger dmerge;
    OMerger omerge;
    Applier app;

    explicit LazySegmentTree(int n,
                             T d_unit, E o_unit,
                             DMerger dmerge,
                             OMerger omerge,
                             Applier app)
        : length(1),
          d_unit(d_unit),
          o_unit(o_unit),
          dmerge(dmerge),
          omerge(omerge),
          app(app) {
        while (length < n) length <<= 1;

        dat.assign(length * 2, d_unit);
        ope.assign(length * 2, o_unit);
    }

    template <class Container>
    explicit LazySegmentTree(const Container& elems,
                             T d_unit, E o_unit,
                             DMerger dmerge,
                             OMerger omerge,
                             Applier app)
        : length(1),
          d_unit(d_unit),
          o_unit(o_unit),
          dmerge(dmerge),
          omerge(omerge),
          app(app) {
        int n = elems.size();
        while (length < n) length <<= 1;

        dat.assign(length * 2, d_unit);
        ope.assign(length * 2, o_unit);

        std::copy(elems.begin(), elems.end(), dat.begin() + length);

        for (int nidx = length - 1; nidx >= 1; --nidx) {
            T vl = dat[nidx * 2 + 0];
            T vr = dat[nidx * 2 + 1];
            dat[nidx] = dmerge(vl, vr);
        }
    }

    void propagate(int nidx, int len) {
        if (ope[nidx] == o_unit) return;

        // propagate
        if (len > 1) {
            ope[nidx * 2 + 0] = omerge(ope[nidx * 2 + 0], ope[nidx]);
            ope[nidx * 2 + 1] = omerge(ope[nidx * 2 + 1], ope[nidx]);
        }

        // update data
        dat[nidx] = app(dat[nidx], ope[nidx], len);
        ope[nidx] = o_unit;
    }

    void update(int ql, int qr, E e, int nidx, int nl, int nr) {
        propagate(nidx, nr - nl);

        if (nr <= ql || qr <= nl) return;
        if (ql <= nl && nr <= qr) {
            ope[nidx] = omerge(ope[nidx], e);
            propagate(nidx, nr - nl);
            return;
        }

        int nm = (nl + nr) / 2;
        update(ql, qr, e, nidx * 2 + 0, nl, nm);
        update(ql, qr, e, nidx * 2 + 1, nm, nr);

        // update data
        dat[nidx] = dmerge(dat[nidx * 2 + 0], dat[nidx * 2 + 1]);
    }

    void update(int ql, int qr, E e) { return update(ql, qr, e, 1, 0, length); }

    T fold(int ql, int qr, int nidx, int nl, int nr) {
        propagate(nidx, nr - nl);

        if (nr <= ql || qr <= nl) return d_unit;
        if (ql <= nl && nr <= qr) return dat[nidx];

        int nm = (nl + nr) / 2;
        T vl = fold(ql, qr, nidx * 2 + 0, nl, nm);
        T vr = fold(ql, qr, nidx * 2 + 1, nm, nr);
        return dmerge(vl, vr);
    }

    T fold(int ql, int qr) { return fold(ql, qr, 1, 0, length); }

    T get(int idx) { return fold(idx, idx + 1); }
    T fold_all() { return fold(0, length); }
};

using lint = long long;

void solve() {
    int n, m, q;
    std::cin >> n >> m >> q;

    std::vector<int> ps(m);
    for (auto& p : ps) {
        std::cin >> p;
        --p;
    }

    Graph<> graph(n);
    for (int i = n - 1; i--;) {
        int u, v;
        std::cin >> u >> v;
        graph.span(false, --u, --v);
    }

    HeavyLightDecomposition hld(graph);

    // range add range sum
    LazySegmentTree<lint, lint>
        seg(
            n, 0, 0,
            [](auto a, auto b) { return a + b; },
            [](auto e, auto f) { return e + f; },
            [](auto a, auto e, int k) { return a + e * k; });
    lint base = 0;

    auto vadd = [&](int v, int d) {
        base += hld.dep[v] * d;
        for (auto [l, r] : hld.path(0, v, false)) {
            seg.update(l, r, d);
        }
    };

    for (auto p : ps) vadd(p, 1);

    while (q--) {
        int t;
        std::cin >> t;

        switch (t) {
            case 1: {
                int i, v;
                std::cin >> i >> v;
                --i, --v;

                auto& p = ps[i];
                vadd(p, -1);
                p = v;
                vadd(p, 1);
                break;
            }
            case 2: {
                int v;
                std::cin >> v;
                --v;

                lint ans = base + lint(m) * hld.dep[v];
                for (auto [l, r] : hld.path(0, v, false)) {
                    ans -= seg.fold(l, r) * 2;
                }
                ans += seg.get(0) * 2;

                std::cout << ans << "\n";
                break;
            }
        }
    }
}

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

    solve();

    return 0;
}
0