Submission #1370069

#TimeUsernameProblemLanguageResultExecution timeMemory
1370069domiWind Turbines (EGOI25_windturbines)C++20
100 / 100
2040 ms77492 KiB
#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()

#define lsb(x) (x & (-x))
#define vi vector<int>
#define YES { cout << "YES" << endl; return; }
#define NO { cout << "NO" << endl; return; }

using ll = long long;
using pii = std::pair<int, int>;

const int NMAX = 2e5;
const int LOG = 20;
const int BLOCK_SIZE = 4e2;

using namespace std;

namespace Kruskal_Tree {
    vector<int> T[2 * NMAX + 5];
    vector<array<int, 3>> edges;
    int dsu_par[2 * NMAX + 5];
    int parentNode[2 * NMAX + 5];
    int dfs_order[2 * NMAX + 5];
    int who[2 * NMAX + 5];
    int dep[2 * NMAX + 5];
    int nodeWeight[2 * NMAX + 5];

    int rmq[2 * NMAX + 5][LOG + 5];
    int lg2[2 * NMAX + 5];

    int ptr;
    int N = 0;
    int mst_cost = 0;
    int timer;

    inline void add_edge(int u, int v, int w) {
        edges.push_back({w, u, v});
        N = max({N, u, v});
    }

    inline int dsu_root(int x) {
        if (x == dsu_par[x]) return x;
        return dsu_par[x] = dsu_root(dsu_par[x]);
    }

    void dfs(int nod, int p = 0) {
        dfs_order[nod] = ++timer;
        who[timer] = nod;
        dep[nod] = dep[p] + 1;

        for (auto &son : T[nod]) {
            if (son == p) continue;
            dfs(son, nod);
        }
    }

    inline int merge(int x, int y) {
        return (dep[x] < dep[y] ? x : y);
    }

    void init() {
        sort(all(edges));
        iota(dsu_par + 1, dsu_par + N + 1, 1LL);
        ptr = N;
        for (auto &[w, u, v] : edges) {
            u = dsu_root(u), v = dsu_root(v);
            if (u == v) continue;

            ++ptr;
            parentNode[u] = ptr;
            parentNode[v] = ptr;

            T[ptr].push_back(u);
            T[ptr].push_back(v);

            nodeWeight[ptr] = w;

            dsu_par[u] = ptr;
            dsu_par[v] = ptr;
            dsu_par[ptr] = ptr;

            mst_cost += w;
        }

        timer = 0;
        dfs(ptr);

        lg2[0] = -1;
        for (int i = 1; i <= timer; ++i) {
            rmq[i][0] = parentNode[who[i]];
            lg2[i] = lg2[i >> 1] + 1;
        }

        for (int j = 1; j <= LOG; ++j){
            for (int i = 1; i + (1LL << j) - 1 <= timer; ++i)
                rmq[i][j] = merge(rmq[i][j - 1], rmq[i + (1LL << (j - 1))][j - 1]);
        }
    }

    inline int lca(int u, int v) {
        if (u == v) return u;

        u = dfs_order[u], v = dfs_order[v];
        if (u > v) swap(u, v);

        int len = v - u + 1;
        int k = lg2[len];

        return merge(rmq[u][k], rmq[v - (1LL << k) + 1][k]);
    }
}

using namespace Kruskal_Tree;

vector<array<int, 3>> queries[BLOCK_SIZE + 5];
int prv[NMAX + 5], nxt[NMAX + 5], cur_prv[NMAX + 5], cur_nxt[NMAX + 5];
int ans[NMAX + 5], n, m, q, cur_cost;

inline void remove_node(int nod) {
    int L = cur_prv[nod];
    int R = cur_nxt[nod];

    if (L && R){
        cur_nxt[L] = R;
        cur_prv[R] = L;

        cur_cost += nodeWeight[lca(L, R)];
        cur_cost -= nodeWeight[lca(nod, L)];
        cur_cost -= nodeWeight[lca(nod, R)];
    }
    else if (L) {
        cur_nxt[L] = 0;
        cur_cost -= nodeWeight[lca(L, nod)];
    }
    else if (R) {
        cur_prv[R] = 0;
        cur_cost -= nodeWeight[lca(nod, R)];
    }
}

inline void add_node(int nod) {
    int L = cur_prv[nod];
    int R = cur_nxt[nod];

    if (L && R) {
        cur_nxt[L] = nod;
        cur_prv[R] = nod;

        cur_cost -= nodeWeight[lca(L, R)];
        cur_cost += nodeWeight[lca(nod, L)];
        cur_cost += nodeWeight[lca(nod, R)];
    }
    else if (L) {
        cur_nxt[L] = nod;
        cur_cost += nodeWeight[lca(nod, L)];
    }
    else if (R) {
        cur_prv[R] = nod;
        cur_cost += nodeWeight[lca(nod, R)];
    }
}

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> n >> m >> q;

    for (int i = 0, u, v, w; i < m; ++i) {
        cin >> u >> v >> w;
        ++u, ++v;
        Kruskal_Tree::add_edge(u, v, w);
    }

    int cnt_blocks = (n - 1) / BLOCK_SIZE + 1;
    for (int i = 1, l, r; i <= q; ++i) {
        cin >> l >> r;
        ++l, ++r;

        int cur_block = (l - 1) / BLOCK_SIZE + 1;
        queries[cur_block].push_back({l, r, i});
    }

    Kruskal_Tree::init();
    vector<pair<int, int>> srt;
    srt.reserve(n);
    for (int u = 1; u <= n; ++u)
        srt.push_back({dfs_order[u], u});

    sort(all(srt));
    for (int i = 0; i < n; ++i) {
        auto [t, u] = srt[i];

        if (i - 1 >= 0)
            prv[u] = srt[i - 1].se;

        if (i + 1 < n)
            nxt[u] = srt[i + 1].se;
    }

    for (int block = 1; block <= cnt_blocks; ++block) {
        if (queries[block].empty()) continue;

        sort(all(queries[block]), [&](auto& a, auto& b) {
            return a[1] > b[1];
        });

        for (int i = 1; i <= n; ++i) {
            cur_prv[i] = prv[i];
            cur_nxt[i] = nxt[i];
        }

        int minL = INT_MAX;
        for (auto &[l, r, idx] : queries[block])
            minL = min(minL, l);

        cur_cost = mst_cost;
        for (int u = 1; u <= minL - 1; ++u)
            remove_node(u);

        int dr = n;
        for (auto &[l, r, idx] : queries[block]) {
            while (dr > r)
                remove_node(dr--);

            for (int u = minL; u <= l - 1; ++u)
                remove_node(u);

            ans[idx] = mst_cost - cur_cost;
            for (int u = l - 1; u >= minL; --u)
                add_node(u);
        }
    }

    for (int i = 1; i <= q; ++i)
        cout << ans[i] << '\n';
    return 0;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...