제출 #1336349

#제출 시각아이디문제언어결과실행 시간메모리
1336349MisterReaperWorst Reporter 4 (JOI21_worst_reporter4)C++20
100 / 100
655 ms351524 KiB
#include <bits/stdc++.h>

using i64 = long long;

#ifdef DEBUG
    #include "debug.h"
#else
    #define debug(...) void(23)
#endif

constexpr i64 inf = i64(1E18);

struct node {
    i64 mn = 0;
    i64 lzadd = 0;
    i64 lzmin = inf;
    int lc = 0;
    int rc = 0;
    int same = true;
    node(i64 x = 0) : mn(x), lzadd(x) {}
    void add(i64 x) {
        mn += x;
        lzadd += x;
        lzmin += x;
    }
    void chmin(i64 x) {
        if (mn >= x) {
            same = true;
        }
        mn = std::min(mn, x);
        lzmin = std::min(lzmin, x);
    }
};

std::vector<node> tree(1);

int new_node(i64 x = 0) {
    tree.emplace_back(x);
    return int(tree.size()) - 1;
}

void push(int v) {
    if (!tree[v].lc) {
        tree[v].lc = new_node(std::min(tree[v].lzadd, tree[v].lzmin));
        tree[v].rc = new_node(std::min(tree[v].lzadd, tree[v].lzmin));
        tree[v].lzadd = 0;
        tree[v].lzmin = inf;
    } else {
        tree[tree[v].lc].add(tree[v].lzadd);
        tree[tree[v].rc].add(tree[v].lzadd);
        tree[tree[v].lc].chmin(tree[v].lzmin);
        tree[tree[v].rc].chmin(tree[v].lzmin);
        tree[v].lzadd = 0;
        tree[v].lzmin = inf;
    }
}

void pull(int v) {
    tree[v].mn = std::min(tree[tree[v].lc].mn, tree[tree[v].rc].mn);
    tree[v].same = tree[tree[v].lc].same && tree[tree[v].rc].same && tree[tree[v].lc].mn == tree[tree[v].rc].mn;
}

void add(int v, int l, int r, int p, i64 x) {
    if (l == r) {
        tree[v].add(x);
        return;
    }
    push(v);
    int mid = (l + r) >> 1;
    if (p <= mid) {
        add(tree[v].lc, l, mid, p, x);
    } else {
        add(tree[v].rc, mid + 1, r, p, x);
    } 
    pull(v);
}

void chmin(int v, int l, int r, int p, i64 x) {
    // debug(v, l, r, p, x);
    if (r == p) {
        tree[v].chmin(x);
        return;
    }
    push(v);
    int mid = (l + r) >> 1;
    if (p <= mid) {
        chmin(tree[v].lc, l, mid, p, x);
    } else {
        tree[tree[v].lc].chmin(x);
        chmin(tree[v].rc, mid + 1, r, p, x);
    }
    pull(v);
}

i64 get(int v, int l, int r, int p) {
    if (tree[v].same) {
        return tree[v].mn;
    }
    push(v);
    int mid = (l + r) >> 1;
    if (p <= mid) {
        return get(tree[v].lc, l, mid, p);
    } else {
        return get(tree[v].rc, mid + 1, r, p);
    }
}

int merge(int lv, int rv, int l, int r) {
    if (tree[lv].same) {
        tree[rv].add(tree[lv].mn);
        return rv;
    } else if (tree[rv].same) {
        tree[lv].add(tree[rv].mn);
        return lv;
    }
    push(lv);
    push(rv);
    int mid = (l + r) >> 1;
    tree[lv].lc = merge(tree[lv].lc, tree[rv].lc, l, mid);
    tree[lv].rc = merge(tree[lv].rc, tree[rv].rc, mid + 1, r);
    pull(lv);
    return lv;
}

void debug_tree(int v, int l, int r) {
    if (tree[v].same) {
        for (int i = l; i <= r; ++i) {
            std::cerr << i << " :: " << tree[v].mn << '\n';
        }
        return;
    }
    int mid = (l + r) >> 1;
    debug_tree(tree[v].lc, l, mid);
    debug_tree(tree[v].rc, mid + 1, r);
}

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

    int N;
    std::cin >> N;

    std::vector<int> A(N), H(N), C(N);
    for (int i = 0; i < N; ++i) {
        std::cin >> A[i] >> H[i] >> C[i];
        --A[i];
    }

    std::vector<int> ids(H.begin(), H.end());
    std::sort(ids.begin(), ids.end());
    ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
    int n = int(ids.size());

    for (int i = 0; i < N; ++i) {
        H[i] = int(std::lower_bound(ids.begin(), ids.end(), H[i]) - ids.begin());
    }

    i64 ans = 0;
    std::vector<int> f(N);
    std::vector<int> deg(N);
    std::vector<int> on_cycle(N, true);
    for (int i = 0; i < N; ++i) {
        f[i] = new_node(0);
        deg[A[i]] += 1;
    }

    std::queue<int> que;
    for (int i = 0; i < N; ++i) {
        if (deg[i] == 0) {
            que.emplace(i);
        }
    }

    while (!que.empty()) {
        auto v = que.front();
        que.pop();
        on_cycle[v] = false;
        if (--deg[A[v]] == 0) {
            que.emplace(A[v]);
        }
    }

    std::vector<int> vis(N);
    std::vector<std::vector<int>> cycles;
    for (int i = 0; i < N; ++i) {
        if (vis[i] || !on_cycle[i]) {
            continue;
        }
        std::vector<int> cyc;
        int u = i;
        do {
            vis[u] = true;
            cyc.emplace_back(u);
            u = A[u];
        } while (u != i);
        cycles.emplace_back(cyc);
    }

    std::vector<std::vector<int>> adj(N);
    for (int i = 0; i < N; ++i) {
        if (!on_cycle[i]) {
            adj[A[i]].emplace_back(i);
        }
    }

    auto dfs = [&](auto&& self, int v) -> void {
        for (auto u : adj[v]) {
            self(self, u);
            f[v] = merge(f[v], f[u], 0, n - 1);
        }
        tree[f[v]].add(C[v]);
        // std::cerr << v << ":\n";
        // debug_tree(f[v], 0, n - 1);
        add(f[v], 0, n - 1, H[v], -C[v]);
        // std::cerr << v << ":\n";
        // debug_tree(f[v], 0, n - 1);
        chmin(f[v], 0, n - 1, H[v], get(f[v], 0, n - 1, H[v]));
        // std::cerr << v << ":\n";
        // debug_tree(f[v], 0, n - 1);
    };

    for (auto cyc : cycles) {
        debug(cyc);
        int root = cyc[0];
        i64 sum = 0;
        for (auto v : cyc) {
            sum += C[v];
            for (auto u : adj[v]) {
                dfs(dfs, u);
                f[root] = merge(f[root], f[u], 0, n - 1);
            }
        }
        tree[f[root]].add(sum);
        for (auto v : cyc) {
            add(f[root], 0, n - 1, H[v], -C[v]);
        }
        ans += tree[f[root]].mn;
    }

    std::cout << ans << '\n';

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...