Submission #1305966

#TimeUsernameProblemLanguageResultExecution timeMemory
1305966orzorzorzFireworks (APIO16_fireworks)C++20
0 / 100
13 ms19236 KiB
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

const int MAXN = 600005;

// We use an array of priority queues, one for each node
priority_queue<long long> pq[MAXN];
vector<pair<int, int>> adj[MAXN];
int leaf_count[MAXN];
long long total_edge_weight = 0;

void solve(int u) {
    if (adj[u].empty()) {
        // Leaf node initialization
        leaf_count[u] = 1;
        pq[u].push(0);
        pq[u].push(0);
        return;
    }

    for (auto& edge : adj[u]) {
        int v = edge.first;
        int w = edge.second;
        
        solve(v);
        leaf_count[u] += leaf_count[v];

        // 1. Merge child's pq into parent's pq (Small-to-Large)
        if (pq[u].size() < pq[v].size()) {
            swap(pq[u], pq[v]);
        }
        while (!pq[v].empty()) {
            pq[u].push(pq[v].top());
            pq[v].pop();
        }
    }

    // 2. Adjust the slope for the edge connecting u to its parent
    // We only need to do this if u is not the root (1)
    // The slope increases by 1 at each breakpoint. To keep slope <= 1:
    while (pq[u].size() > leaf_count[u] + 1) {
        pq[u].pop();
    }

    // 3. Take the two largest breakpoints (the flat [L, R] region)
    long long R = pq[u].top(); pq[u].pop();
    long long L = pq[u].top(); pq[u].pop();

    // 4. Shift them by the edge weight leading to u
    // Note: In this specific implementation, we handle the edge of 'u' 
    // inside the 'solve(u)' call.
}

// Refined Main Loop for the Edge Shift Logic
int main() {
    ios::sync_with_stdio(false); cin.tie(0);

    int n, m;
    cin >> n >> m;

    vector<int> parent(n + m + 1);
    vector<int> weight(n + m + 1);

    for (int i = 2; i <= n + m; i++) {
        cin >> parent[i] >> weight[i];
        adj[parent[i]].push_back({i, weight[i]});
        total_edge_weight += weight[i];
    }

    // Post-order traversal logic (Bottom-up)
    for (int i = n + m; i >= 2; i--) {
        if (i > n) { // Leaf
            leaf_count[i] = 1;
            pq[i].push(0); pq[i].push(0);
        } else {
            while (pq[i].size() > leaf_count[i] + 1) pq[i].pop();
            long long R = pq[i].top(); pq[i].pop();
            long long L = pq[i].top(); pq[i].pop();
            pq[i].push(L + weight[i]);
            pq[i].push(R + weight[i]);
        }
        
        // Merge into parent
        int p = parent[i];
        leaf_count[p] += leaf_count[i];
        if (pq[p].size() < pq[i].size()) swap(pq[p], pq[i]);
        while (!pq[i].empty()) {
            pq[p].push(pq[i].top());
            pq[i].pop();
        }
    }

    // Final Root (Node 1) Processing
    // Slope should be 0 at the minimum.
    while (pq[1].size() > leaf_count[1]) {
        pq[1].pop();
    }

    long long ans = total_edge_weight;
    while (!pq[1].empty()) {
        ans -= pq[1].top();
        pq[1].pop();
    }

    cout << ans << endl;
    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...