제출 #1332305

#제출 시각아이디문제언어결과실행 시간메모리
1332305MisterReaperDesignated Cities (JOI19_designated_cities)C++20
100 / 100
1638 ms76968 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);

std::multiset<i64> mset;

#define def int mid = (l + r) >> 1, lv = v + 1, rv = v + ((mid - l + 1) << 1)
struct segtree {
    struct node {
        i64 mx = -inf;
        int p = -1;
    };
    node unite(const node& lhs, const node& rhs) {
        node res;
        if (lhs.mx > rhs.mx) {
            res.mx = lhs.mx;
            res.p = lhs.p;
        } else {
            res.mx = rhs.mx;
            res.p = rhs.p;
        }
        return res;
    }
    int n;
    std::vector<node> tree;
    segtree(int n_) : n(n_), tree(n << 1) {
        auto dfs = [&](auto&& self, int v, int l, int r) -> void {
            if (l == r) {
                tree[v].mx = 0;
                tree[v].p = l;
                return;
            }
            def;
            self(self, lv, l, mid);
            self(self, rv, mid + 1, r);
            tree[v] = unite(tree[lv], tree[rv]);
        };
        dfs(dfs, 0, 0, n - 1);
    }
    void modify(int v, int l, int r, int p, i64 x) {
        if (l == r) {
            mset.erase(mset.find(tree[v].mx));
            tree[v].mx += x;
            mset.insert(tree[v].mx);
            return;
        }
        def;
        if (p <= mid) {
            modify(lv, l, mid, p, x);
        } else {
            modify(rv, mid + 1, r, p, x);
        }
        tree[v] = unite(tree[lv], tree[rv]);
    }
    void modify(int p, i64 x) {
        modify(0, 0, n - 1, p, x);
    }
    node get(int v, int l, int r, int ql, int qr) {
        if (ql == l && r == qr) {
            return tree[v];
        }
        def;
        if (qr <= mid) {
            return get(lv, l, mid, ql, qr);
        } else if (mid + 1 <= ql) {
            return get(rv, mid + 1, r, ql, qr);
        } else {
            return unite(get(lv, l, mid, ql, mid),
                        get(rv, mid + 1, r, mid + 1, qr));
        }
    }
    node get(int l, int r) {
        if (l > r) {
            return node();
        }
        return get(0, 0, n - 1, l, r);
    }
    void add(int l, int r, i64 x) {
        node nd = get(0, 0, n - 1, l, r);
        modify(nd.p, x);
    }
    void add_other(int l, int r, i64 x) {
        node nd = get(0, l - 1);
        nd = unite(nd, get(r + 1, n - 1));
        modify(nd.p, x);
    }
};

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

    int N;
    std::cin >> N;

    for (int i = 0; i < N; ++i) {
        mset.emplace(0);
    }

    std::vector<std::vector<int>> adj(N);
    std::vector<std::array<int, 4>> E(N);
    for (int i = 1; i < N; ++i) {
        std::cin >> E[i][0] >> E[i][1] >> E[i][2] >> E[i][3];
        --E[i][0], --E[i][1];
        adj[E[i][0]].emplace_back(i);
        adj[E[i][1]].emplace_back(i);
    }

    int tim = 0;
    std::vector<int> tin(N), tout(N);
    auto init = [&](auto&& self, int v, int pr) -> void {
        tin[v] = tim++;
        for (auto i : adj[v]) {
            int u = E[i][0] ^ E[i][1] ^ v;
            if (u == pr) {
                continue;
            }
            self(self, u, v);
        }
        tout[v] = tim - 1;
    };
    init(init, 0, -1);

    std::vector<i64> anses(N, i64(1E18));

    auto cost = [&](int i, int u, int v) -> int {
        if (E[i][0] == u && E[i][1] == v) {
            return E[i][2];
        } else {
            assert(E[i][0] == v && E[i][1] == u);
            return E[i][3];
        }
    };

    std::vector<i64> f(N);
    segtree seg(N);
    auto dfs1 = [&](auto&& self, int v, int pr) -> void {
        for (auto i : adj[v]) {
            int u = E[i][0] ^ E[i][1] ^ v;
            if (u == pr) {
                continue;
            }
            self(self, u, v);
            seg.add(tin[u], tout[u], cost(i, v, u));
            f[v] += f[u];
            f[v] += cost(i, v, u);
        }
    };
    dfs1(dfs1, 0, -1);

    int special = -1, aux = -1;

    auto dfs2 = [&](auto&& self, int v, int pr) -> void {
        if (special == -1) {
            auto it = mset.rbegin();
            i64 cur = 0;
            for (int i = 0; i < 2; ++i) {
                // std::cerr << f[v] - cur << " \n"[i == N - 1];
                if (i == 1 && f[v] - cur < anses[i]) {
                    aux = v;
                }
                anses[i] = std::min(anses[i], f[v] - cur);
                cur += *it;
                ++it;
            }
        } else if (v == aux) {
            auto it = mset.rbegin();
            i64 cur = 0;
            for (int i = 0; i < N; ++i) {
                // std::cerr << f[v] - cur << " \n"[i == N - 1];
                anses[i] = std::min(anses[i], f[v] - cur);
                cur += *it;
                ++it;
            }
        }
        for (auto i : adj[v]) {
            int u = E[i][0] ^ E[i][1] ^ v;
            if (u == pr) {
                continue;
            }
            f[v] -= f[u];
            f[v] -= cost(i, v, u);
            seg.add(tin[u], tout[u], -cost(i, v, u));
            f[u] += f[v];
            f[u] += cost(i, u, v);
            seg.add_other(tin[u], tout[u], cost(i, u, v));
            self(self, u, v);
            f[u] -= f[v];
            f[u] -= cost(i, u, v);
            seg.add_other(tin[u], tout[u], -cost(i, u, v));
            f[v] += f[u];
            f[v] += cost(i, v, u);
            seg.add(tin[u], tout[u], cost(i, v, u));
        }
    };
    dfs2(dfs2, 0, -1);
    special = aux;
    dfs2(dfs2, 0, -1);

    debug(anses);

    int Q;
    std::cin >> Q;

    while (Q--) {
        int K;
        std::cin >> K;
        std::cout << anses[K - 1] << '\n';
    }

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