제출 #1333141

#제출 시각아이디문제언어결과실행 시간메모리
1333141mamabearWind Turbines (EGOI25_windturbines)C++20
8 / 100
2196 ms46004 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

struct Edge {
    int u, v;
    long long w;
    bool operator<(const Edge& o) const {
        return w < o.w;
    }
};

struct Query {
    int l, r, id;
};

const int MAXN = 100005;

int parent_dsu[MAXN];
int find_set(int v) {
    if (v == parent_dsu[v]) return v;
    return parent_dsu[v] = find_set(parent_dsu[v]);
}

vector<pair<int, long long>> adj[MAXN];
long long dist_root[MAXN];
int tin[MAXN], timer_tin = 0;
int euler[2 * MAXN], euler_depth[2 * MAXN], first_occ[MAXN], timer_euler = 0;

void dfs(int u, int p, int d, long long current_dist) {
    tin[u] = timer_tin++;
    dist_root[u] = current_dist;
    first_occ[u] = timer_euler;
    euler[timer_euler] = u;
    euler_depth[timer_euler] = d;
    timer_euler++;

    for (auto& edge : adj[u]) {
        int v = edge.first;
        long long w = edge.second;
        if (v != p) {
            dfs(v, u, d + 1, current_dist + w);
            euler[timer_euler] = u;
            euler_depth[timer_euler] = d;
            timer_euler++;
        }
    }
}

int st[20][2 * MAXN];
int lg[2 * MAXN];

void build_rmq() {
    lg[1] = 0;
    for (int i = 2; i <= timer_euler; i++) lg[i] = lg[i / 2] + 1;
    for (int i = 0; i < timer_euler; i++) st[0][i] = i;
    for (int j = 1; (1 << j) <= timer_euler; j++) {
        for (int i = 0; i + (1 << j) <= timer_euler; i++) {
            int left = st[j - 1][i];
            int right = st[j - 1][i + (1 << (j - 1))];
            st[j][i] = (euler_depth[left] < euler_depth[right]) ? left : right;
        }
    }
}

int get_lca(int u, int v) {
    int l = first_occ[u];
    int r = first_occ[v];
    if (l > r) swap(l, r);
    int j = lg[r - l + 1];
    int left = st[j][l];
    int right = st[j][r - (1 << j) + 1];
    return (euler_depth[left] < euler_depth[right]) ? euler[left] : euler[right];
}

long long get_dist(int u, int v) {
    return dist_root[u] + dist_root[v] - 2 * dist_root[get_lca(u, v)];
}

struct DLLNode {
    int prev, next;
} dll[MAXN];

long long current_VT_weight2 = 0;

struct State {
    int u;
    long long old_weight;
};
vector<State> history;

void delete_node(int u, bool save) {
    if (save) history.push_back({u, current_VT_weight2});
    int p = dll[u].prev;
    int n = dll[u].next;
    if (p != u) {
        current_VT_weight2 -= get_dist(p, u);
        current_VT_weight2 -= get_dist(u, n);
        current_VT_weight2 += get_dist(p, n);
        dll[p].next = n;
        dll[n].prev = p;
    } else {
        current_VT_weight2 = 0;
    }
}

void undo() {
    State s = history.back();
    history.pop_back();
    int u = s.u;
    current_VT_weight2 = s.old_weight;
    int p = dll[u].prev;
    int n = dll[u].next;
    if (p != u) {
        dll[p].next = u;
        dll[n].prev = u;
    }
}

long long solve_small(int l, int r) {
    if (l == r) return 0;
    vector<int> nodes;
    for (int i = l; i <= r; i++) nodes.push_back(i);
    sort(nodes.begin(), nodes.end(), [](int a, int b) {
        return tin[a] < tin[b];
    });
    long long wt2 = 0;
    int k = nodes.size();
    for (int i = 0; i < k; i++) {
        wt2 += get_dist(nodes[i], nodes[(i + 1) % k]);
    }
    return wt2 / 2;
}

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

    int N, M, Q;
    if (!(cin >> N >> M >> Q)) return 0;

    vector<Edge> edges(M);
    for (int i = 0; i < M; i++) {
        cin >> edges[i].u >> edges[i].v >> edges[i].w;
    }
    sort(edges.begin(), edges.end());

    for (int i = 0; i < N; i++) parent_dsu[i] = i;

    long long W_MST = 0;
    for (int i = 0; i < M; i++) {
        int pu = find_set(edges[i].u);
        int pv = find_set(edges[i].v);
        if (pu != pv) {
            parent_dsu[pu] = pv;
            adj[edges[i].u].push_back({edges[i].v, edges[i].w});
            adj[edges[i].v].push_back({edges[i].u, edges[i].w});
            W_MST += edges[i].w;
        }
    }

    dfs(0, -1, 0, 0);
    build_rmq();

    vector<int> global_order(N);
    for (int i = 0; i < N; i++) global_order[i] = i;
    sort(global_order.begin(), global_order.end(), [](int a, int b) {
        return tin[a] < tin[b];
    });

    vector<Query> queries(Q);
    for (int i = 0; i < Q; i++) {
        cin >> queries[i].l >> queries[i].r;
        queries[i].id = i;
    }

    int B = max(1, (int)(N / sqrt(Q)));
    vector<Query> diff_block_queries;
    vector<long long> ans(Q);

    for (int i = 0; i < Q; i++) {
        if (queries[i].l / B == queries[i].r / B) {
            ans[queries[i].id] = W_MST - solve_small(queries[i].l, queries[i].r);
        } else {
            diff_block_queries.push_back(queries[i]);
        }
    }

    sort(diff_block_queries.begin(), diff_block_queries.end(), [&](const Query& a, const Query& b) {
        int ba = a.l / B;
        int bb = b.l / B;
        if (ba != bb) return ba < bb;
        return a.r > b.r;
    });

    int num_blocks = (N / B) + 1;
    int q_idx = 0;
    int num_diff = diff_block_queries.size();

    for (int b = 0; b < num_blocks && q_idx < num_diff; b++) {
        if (diff_block_queries[q_idx].l / B != b) continue;

        int block_start = b * B;
        
        vector<int> nodes_in_suffix;
        for (int i = 0; i < N; i++) {
            if (global_order[i] >= block_start) {
                nodes_in_suffix.push_back(global_order[i]);
            }
        }

        int V = nodes_in_suffix.size();
        current_VT_weight2 = 0;

        if (V > 0) {
            for (int i = 0; i < V; i++) {
                int u = nodes_in_suffix[i];
                int nxt = nodes_in_suffix[(i + 1) % V];
                int prv = nodes_in_suffix[(i - 1 + V) % V];
                dll[u].next = nxt;
                dll[u].prev = prv;
                current_VT_weight2 += get_dist(u, nxt);
            }
        }

        int curr_R = N - 1;

        while (q_idx < num_diff && diff_block_queries[q_idx].l / B == b) {
            int L = diff_block_queries[q_idx].l;
            int R = diff_block_queries[q_idx].r;
            int id = diff_block_queries[q_idx].id;

            while (curr_R > R) {
                delete_node(curr_R, false);
                curr_R--;
            }

            int saves = 0;
            for (int x = block_start; x < L; x++) {
                delete_node(x, true);
                saves++;
            }

            ans[id] = W_MST - current_VT_weight2 / 2;

            for (int i = 0; i < saves; i++) {
                undo();
            }

            q_idx++;
        }
    }

    for (int i = 0; i < Q; i++) cout << ans[i] << "\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...