Submission #412323

#TimeUsernameProblemLanguageResultExecution timeMemory
412323model_codeRoad Closures (APIO21_roads)C++17
100 / 100
295 ms42292 KiB
#include "roads.h" #include <bits/stdc++.h> std::vector<std::priority_queue<long long>> used_edges, free_edges; std::vector<std::vector<long long>> neighbouring_edges; std::vector<int> last_limit, degree; std::vector<long long> full_dp, partial_dp, used_sum; std::vector<std::set<std::pair<int, int>>> tree; long long get(int v, int limit) { if (limit <= 0) return 0; auto & used_pq = used_edges[v]; auto & free_pq = free_edges[v]; auto & sum = used_sum[v]; while ((int)used_pq.size() > limit) { int w = -used_pq.top(); used_pq.pop(); sum -= w; free_pq.push(w); } while ((int)used_pq.size() < limit && free_pq.size() > 0) { int w = free_pq.top(); free_pq.pop(); sum += w; used_pq.push(-w); } while (used_pq.size() > 0 && free_pq.size() > 0 && -used_pq.top() < free_pq.top()) { sum += free_pq.top() + used_pq.top(); used_pq.push(-free_pq.top()); free_pq.push(-used_pq.top()); used_pq.pop(); free_pq.pop(); } int remaining_slots = limit - used_pq.size(); long long ans = sum; for (long long x : neighbouring_edges[v]) { if (x < 0) break; if (remaining_slots > 0) { ans += x; --remaining_slots; continue; } if (used_pq.size() > 0 && -used_pq.top() < x) { ans += x + used_pq.top(); sum += used_pq.top(); free_pq.push(-used_pq.top()); used_pq.pop(); } } return ans; } void dfs(int v, int par, int limit) { assert(degree[v] > limit); last_limit[v] = limit; full_dp[v] = partial_dp[v] = 0; neighbouring_edges[v].clear(); for (auto & e : tree[v]) { int u, w; std::tie(u, w) = e; if (u == par) continue; dfs(u, v, limit); partial_dp[v] += full_dp[u]; neighbouring_edges[v].push_back(w + partial_dp[u] - full_dp[u]); } sort(neighbouring_edges[v].rbegin(), neighbouring_edges[v].rend()); long long cursum = partial_dp[v]; partial_dp[v] = cursum + get(v, limit-1); full_dp[v] = cursum + get(v, limit); } std::vector<long long> minimum_closure_costs(int N, std::vector<int> U, std::vector<int> V, std::vector<int> W) { free_edges.resize(N); used_edges.resize(N); neighbouring_edges.resize(N); last_limit.resize(N, 0); long long total = std::accumulate(W.begin(), W.end(), 0LL); full_dp.resize(N); partial_dp.resize(N); used_sum.resize(N, 0); tree.resize(N); for (int i = 0; i < N-1; ++i) { tree[U[i]].insert({V[i], W[i]}); tree[V[i]].insert({U[i], W[i]}); } degree.resize(N); for (int i = 0; i < N; ++i) degree[i] = tree[i].size(); std::vector<int> nodes(N); std::iota(nodes.begin(), nodes.end(), 0); std::sort(nodes.begin(), nodes.end(), [&](int lef, int rig) { return degree[lef] > degree[rig]; }); int last = N-1; long long totally_free = 0; std::vector<long long> ans(N, total); for (int k = 1; k < N; ++k) { while (last >= 0 && degree[nodes[last]] <= k) { int v = nodes[last]; for (auto & e : tree[v]) { int u, w; std::tie(u, w) = e; assert(tree[u].count({v, w})); tree[u].erase({v, w}); free_edges[u].push(w); } while (!free_edges[v].empty()) { totally_free += free_edges[v].top(); free_edges[v].pop(); } totally_free += used_sum[v]; tree[v].clear(); --last; } ans[k] -= totally_free; for (int v : nodes) { if (degree[v] <= k) break; if (last_limit[v] >= k) continue; dfs(v, v, k); ans[k] -= full_dp[v]; } } return ans; }
#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...