提出 #52811611


ソースコード 拡げる

#include <bits/stdc++.h>
#include "atcoder/modint"
#include "atcoder/segtree"

using namespace std;
using ll = long long;

template <class T>
T rd() {
    T ret;
    cin >> ret;
    return ret;
}

// Coding Space

struct HLD {
    int n;
    vector<vector<int>> g;
    vector<int> in, head, par, siz, nxt, tleaf, rev, bord;

    void dfs1(const int v, const int p) {
        siz[v] = 1;
        par[v] = p;
        for (int &t : g[v]) {
            dfs1(t, v);
            siz[v] += siz[t];
            if (siz[t] > siz[g[v][0]]) {
                swap(t, g[v][0]);
            }
        }
    }

    int dfs2(const int v, int &id) {
        in[v] = id;
        rev[id] = v;
        ++id;
        int ret = v;
        for (const int t : g[v]) {
            head[t] = t == g[v][0] ? head[v] : t;
            int res = dfs2(t, id);
            if (t == g[v][0]) {
                nxt[v] = t;
                ret = res;
            }
        }
        // out[v] = id++;
        return tleaf[v] = ret;
    }

    void bfs(int root) {
        queue<int> que;
        que.push(root);
        int id = 0;
        while (not que.empty()) {
            const auto f = que.front();
            que.pop();
            bord[f] = id++;
            for (const int t : g[f]) {
                que.push(t);
            }
        }
    }

    HLD(const vector<vector<int>> &g_) : 
        n(g_.size()), g(g_), in(n, -1), head(n, -1), par(n, -1), siz(n, -1), nxt(n, -1), tleaf(n, -1), rev(n, -1), bord(n, -1) {
        dfs1(0, -1);
        int gomi = 0;
        head[0] = 0;
        dfs2(0, gomi);
        bfs(0);
    }

    vector<pair<int, int>> get_ranges(int v) {
        vector<pair<int, int>> ret;
        while (v != -1) {
            ret.push_back({in[head[v]], in[v]});
            v = par[head[v]];
        }
        return ret;
    }
};

using Fp = atcoder::modint998244353;

struct Node {
    Fp a;
    Fp b;
};

Node op(const Node &x, const Node &y) {
    return {y.a * x.a, y.b * x.a + x.b};
}
Node e() {
    return {1, 0};
}

Fp op_mul(Fp a, Fp b) {
    return a * b;
}
Fp e_mul() {
    return 1;
}

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

    // in
    const int n = rd<int>(), q = rd<int>();
    vector<int> p(n, -1);
    vector<vector<int>> g(n);
    for (int i = 1; i < n; ++i) {
        p[i] = rd<int>() - 1;
        g[p[i]].push_back(i);
    }
    vector<int> a(n);
    for (auto &e : a) {
        e = rd<int>();
    }
    
    vector<pair<int, int>> qs(q);
    for (auto &[v, x] : qs) {
        v = rd<int>() - 1;
        x = rd<int>();
    }

    // solve
    HLD hld_tree(g);

    vector<Fp> init_f(n);
    for (int i = n - 1; i >= 0; --i) {
        if (g[i].empty()) {
            init_f[i] = a[i];
        } else {
            init_f[i] = a[i];
            Fp x = 1;
            for (const int t : g[i]) {
                x *= init_f[t];
            }
            init_f[i] += x;
        }
    }

    vector<Node> vec_ordered(n);
    for (int i = 0; i < n; ++i) {
        const int v = hld_tree.rev[i];
        Fp mul = 1;
        for (const int t : g[v]) {
            if (t != hld_tree.nxt[v]) {
                mul *= init_f[t];
            }
        }
        if (g[v].empty()) {
            mul = 0;
        }
        vec_ordered[i] = {mul, a[v]};
    }

    vector<Fp> f_bord(n);
    for (int i = 0; i < n; ++i) {
        f_bord[hld_tree.bord[i]] = init_f[i];
    }

    atcoder::segtree<Node, op, e> seg(vec_ordered);
    atcoder::segtree<Fp, op_mul, e_mul> seg_bord(f_bord);

    vector<Fp> ans(q);

    auto upd = [&](const int v) {
        const int l = hld_tree.g[v][0], r = hld_tree.g[v].back();
        const int m = hld_tree.nxt[v];
        Fp x = seg_bord.prod(hld_tree.bord[l], hld_tree.bord[m]);
        Fp y = seg_bord.prod(hld_tree.bord[m] + 1, hld_tree.bord[r] + 1);
        seg.set(hld_tree.in[v], {x * y, a[v]});
    };

    auto calc_f = [&](const int v) {
        const int l = hld_tree.in[v];
        const int r = hld_tree.in[hld_tree.tleaf[v]] + 1;
        const auto res = seg.prod(l, r);
        return res.b;
    };

    for (int qi = 0; qi < q; ++qi) {
        const auto &[v, x] = qs[qi];
        a[v] = x;
        seg.set(hld_tree.in[v], {seg.get(hld_tree.in[v]).a, a[v]});

        auto rs = hld_tree.get_ranges(v);
        for (const auto &[l, r] : rs) {
            if (l == 0) {
                continue;
            }
            const int l_id = hld_tree.rev[l];
            seg_bord.set(hld_tree.bord[l_id], calc_f(l_id));
            const int head_id = hld_tree.par[hld_tree.head[l_id]];
            upd(head_id);
        }

        ans[qi] = calc_f(0);
    }

    for (const auto e : ans) {
        cout << e.val() << '\n';
    }
}

提出情報

提出日時
問題 G - Hash on Tree
ユーザ Cyanmond
言語 C++ 20 (gcc 12.2)
得点 650
コード長 4919 Byte
結果 AC
実行時間 567 ms
メモリ 56904 KiB

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 650 / 650
結果
AC × 3
AC × 46
セット名 テストケース
Sample 00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt
All 00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt, 01_random_00.txt, 01_random_01.txt, 01_random_02.txt, 01_random_03.txt, 02_random_max_00.txt, 02_random_max_01.txt, 02_random_max_02.txt, 02_random_max_03.txt, 03_path_00.txt, 04_star_00.txt, 04_star_01.txt, 04_star_02.txt, 04_star_03.txt, 05_centipede_00.txt, 05_centipede_01.txt, 05_centipede_02.txt, 05_centipede_03.txt, 05_centipede_04.txt, 05_centipede_05.txt, 05_centipede_06.txt, 05_centipede_07.txt, 05_centipede_08.txt, 05_centipede_09.txt, 05_centipede_10.txt, 05_centipede_11.txt, 06_n-ary_00.txt, 06_n-ary_01.txt, 06_n-ary_02.txt, 06_n-ary_03.txt, 06_n-ary_04.txt, 06_n-ary_05.txt, 06_n-ary_06.txt, 06_n-ary_07.txt, 06_n-ary_08.txt, 06_n-ary_09.txt, 07_corner_00.txt, 08_hld_worst_complexity_00.txt, 08_hld_worst_complexity_01.txt, 08_hld_worst_complexity_02.txt, 08_hld_worst_complexity_03.txt, 08_hld_worst_complexity_04.txt, 09_corner_2_00.txt, 09_corner_2_01.txt
ケース名 結果 実行時間 メモリ
00_sample_00.txt AC 1 ms 3548 KiB
00_sample_01.txt AC 1 ms 3436 KiB
00_sample_02.txt AC 1 ms 3500 KiB
01_random_00.txt AC 404 ms 35280 KiB
01_random_01.txt AC 393 ms 34368 KiB
01_random_02.txt AC 385 ms 32260 KiB
01_random_03.txt AC 250 ms 14428 KiB
02_random_max_00.txt AC 426 ms 38384 KiB
02_random_max_01.txt AC 409 ms 38376 KiB
02_random_max_02.txt AC 402 ms 38332 KiB
02_random_max_03.txt AC 409 ms 38420 KiB
03_path_00.txt AC 121 ms 56904 KiB
04_star_00.txt AC 164 ms 31148 KiB
04_star_01.txt AC 164 ms 33612 KiB
04_star_02.txt AC 181 ms 34448 KiB
04_star_03.txt AC 169 ms 33596 KiB
05_centipede_00.txt AC 145 ms 48824 KiB
05_centipede_01.txt AC 161 ms 48780 KiB
05_centipede_02.txt AC 157 ms 44464 KiB
05_centipede_03.txt AC 171 ms 44512 KiB
05_centipede_04.txt AC 172 ms 36380 KiB
05_centipede_05.txt AC 193 ms 35216 KiB
05_centipede_06.txt AC 177 ms 35852 KiB
05_centipede_07.txt AC 187 ms 36540 KiB
05_centipede_08.txt AC 165 ms 44528 KiB
05_centipede_09.txt AC 167 ms 44472 KiB
05_centipede_10.txt AC 196 ms 41312 KiB
05_centipede_11.txt AC 183 ms 41380 KiB
06_n-ary_00.txt AC 567 ms 38400 KiB
06_n-ary_01.txt AC 505 ms 36500 KiB
06_n-ary_02.txt AC 432 ms 35380 KiB
06_n-ary_03.txt AC 367 ms 34864 KiB
06_n-ary_04.txt AC 274 ms 34036 KiB
06_n-ary_05.txt AC 214 ms 33664 KiB
06_n-ary_06.txt AC 219 ms 33820 KiB
06_n-ary_07.txt AC 167 ms 33760 KiB
06_n-ary_08.txt AC 534 ms 36428 KiB
06_n-ary_09.txt AC 567 ms 36804 KiB
07_corner_00.txt AC 156 ms 44524 KiB
08_hld_worst_complexity_00.txt AC 502 ms 36340 KiB
08_hld_worst_complexity_01.txt AC 462 ms 36916 KiB
08_hld_worst_complexity_02.txt AC 428 ms 37892 KiB
08_hld_worst_complexity_03.txt AC 381 ms 38132 KiB
08_hld_worst_complexity_04.txt AC 319 ms 38748 KiB
09_corner_2_00.txt AC 87 ms 7236 KiB
09_corner_2_01.txt AC 160 ms 33644 KiB