Submission #1305884

#TimeUsernameProblemLanguageResultExecution timeMemory
1305884orzorzorzFireworks (APIO16_fireworks)C++20
0 / 100
5 ms9788 KiB
/** * APIO 2016 - Fireworks * 55+ Point Solution (STL Priority Queue + Small-to-Large Merging) */ #include <iostream> #include <vector> #include <queue> #include <algorithm> using namespace std; const int MAXN = 300005; // Adjacency list: store children indices vector<int> adj[MAXN]; // Edge weights: weight[i] is weight of edge between i and its parent long long edge_weight[MAXN]; // Priority Queue to store breakpoints for each node priority_queue<long long> pq[MAXN]; // Number of leaves in the subtree int num_leaves[MAXN]; void dfs(int u) { // Base Case: If u is a leaf (no children) if (adj[u].empty()) { num_leaves[u] = 1; // Leaf cost function is |x - 0|, breakpoints at 0, 0 // Slope changes from -1 to 0 at 0, and 0 to 1 at 0 pq[u].push(0); pq[u].push(0); return; } num_leaves[u] = 0; for (int v : adj[u]) { dfs(v); num_leaves[u] += num_leaves[v]; // Small-to-Large Merging // Always merge the smaller queue into the larger one to keep complexity low if (pq[u].size() < pq[v].size()) { swap(pq[u], pq[v]); } // Move all elements from child v to parent u while (!pq[v].empty()) { pq[u].push(pq[v].top()); pq[v].pop(); } } // Logic for Internal Nodes (excluding Root for a moment) // We want the slope to eventually reach 1. // The slope starts at -num_leaves[u]. // Each breakpoint increases slope by 1. // To stop at slope 1, we need (num_leaves[u] + 1) breakpoints. // Pop the largest elements (steepest positive slopes) until size fits. // Note: We perform the edge shift logic ONLY if we are NOT the root yet, // or we treat the root specially afterwards. // The standard Slope Trick usually shifts at the child before merging, // or shifts at the node before passing up. Here we process node u completely. // To process the edge above u (connecting u to parent): // 1. Reduce max slope to 1. while (pq[u].size() > num_leaves[u] + 1) { pq[u].pop(); } // 2. Pop top two points (L and R), shift them by edge weight W, push back. long long r = pq[u].top(); pq[u].pop(); long long l = pq[u].top(); pq[u].pop(); pq[u].push(l + edge_weight[u]); pq[u].push(r + edge_weight[u]); } int main() { // Optimize I/O operations ios_base::sync_with_stdio(false); cin.tie(NULL); int n, m; if (!(cin >> n >> m)) return 0; long long total_edge_sum = 0; // Input format: For i from 2 to N+M // P_i (Parent), W_i (Weight) for (int i = 2; i <= n + m; i++) { int p; long long w; cin >> p >> w; adj[p].push_back(i); edge_weight[i] = w; total_edge_sum += w; } // Run DFS from the switch (Node 1) // Note: The DFS above adds the edge weight of 'u' at the end of 'u' processing. // However, Node 1 (Root) has no parent edge. // We need to be careful. The logic inside DFS adds edge_weight[u]. // For root, edge_weight[1] is 0 (global array init), so adding 0 doesn't hurt logic // BUT root requires slope 0, not 1. // Let's adjust DFS slightly or handle root separately. // Simpler: Run DFS for children of root, merge into root, then handle root logic manually. // Re-implementation of Main Loop for Root logic correctness: // We will call a specific DFS that handles the shift internally. // Let's modify the DFS call slightly to be pure. // We can just use the DFS function defined above, but for the Root (Node 1), // we must undo the "slope 1" logic because Root needs slope 0. // Actually, simpler to just implement the logic inside DFS with a check. // Let's rewrite the DFS loop in main to be explicit: for (int v : adj[1]) { dfs(v); num_leaves[1] += num_leaves[v]; if (pq[1].size() < pq[v].size()) swap(pq[1], pq[v]); while (!pq[v].empty()) { pq[1].push(pq[v].top()); pq[v].pop(); } } // Final processing for Root (Node 1) // Root needs to end at slope 0 (optimality condition). // Start slope is -num_leaves[1]. // Target slope is 0. // We need num_leaves[1] breakpoints. while (pq[1].size() > num_leaves[1]) { pq[1].pop(); } // Calculate Answer // Min Cost = Sum of all edge weights - Sum of retained breakpoints // (This is a derived property of the slope trick for this specific problem) long long retained_sum = 0; while (!pq[1].empty()) { retained_sum += pq[1].top(); pq[1].pop(); } cout << total_edge_sum - retained_sum << 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...