Submission #522107

#TimeUsernameProblemLanguageResultExecution timeMemory
522107blueRoad Closures (APIO21_roads)C++17
100 / 100
409 ms166780 KiB
#include <iostream> #include <vector> #include <algorithm> #include <set> using namespace std; using vi = vector<int>; using vvi = vector<vi>; using ll = long long; using vll = vector<ll>; using vvll = vector<vll>; using pii = pair<int, int>; #define sz(x) int(x.size()) const int mx = 100'000; const ll INF = 1'000'000'000'000'000'000LL; int N; vi U, V, W; vi edge[mx]; vi deg(mx, 0); vi deg_occ[mx]; vi depth(mx); vi parent(mx, -1); ll wt_sum = 0; vi par_wt(mx); void dfs1(int u, int p) { for(int e: edge[u]) { int v = U[e] + V[e] - u; int w = W[e]; if(v == p) continue; par_wt[v] = w; depth[v] = depth[u] + 1; parent[v] = u; dfs1(v, u); } } struct segtree { int l; int r; ll sm = 0; int ct = 0; segtree* left = NULL; segtree* right = NULL; segtree() { ; } segtree(int L, int R) { l = L; r = R; sm = 0; ct = 0; } void insert(int v) { // cerr << "enter insert\n"; ct++; sm += v; if(l != r) { if(v <= (l+r)/2) { if(left == NULL) left = new segtree(l, (l+r)/2); left->insert(v); } else { if(right == NULL) right = new segtree((l+r)/2+1, r); right->insert(v); } } // cerr << "exit insert\n"; } ll getsum(ll v) { // cerr << "enter getsum\n"; if(v == 0) { return 0; } else if(l == r) { return ll(l) * v; } else { // cerr << "case 3\n"; if(left != NULL && left->ct >= v) return left->getsum(v); else return (left == NULL ? 0 : left->sm) + right->getsum(v - (left == NULL ? 0 : left->ct)); } // cerr << "exit getsum\n"; } }; struct DS { int curr_size = 0; segtree S = segtree(1, 1'000'000'000); ll minSum(int z) { if(z > curr_size) return INF; else if(z <= 0) return 0; else return S.getsum(z); } void insert(int v) { curr_size++; S.insert(v); } int size() { return curr_size; } }; // struct DS // { // multiset<ll> values; // ll minSum(int z) // { // if(z > sz(values)) return INF; // if(z <= 0) return 0; // int ct = 0; // ll res = 0; // for(ll v : values) // { // res += v; // ct++; // if(ct == z) break; // } // return res; // } // void insert(ll v) // { // values.insert(v); // } // int size() // { // return sz(values); // } // }; vll minimum_closure_costs(int N_, vi U_, vi V_, vi W_) { N = N_; U = U_; V = V_; W = W_; for(int e = 0; e < N-1; e++) { edge[U[e]].push_back(e); edge[V[e]].push_back(e); deg[U[e]]++; deg[V[e]]++; wt_sum += W[e]; } for(int i = 0; i < N; i++) deg_occ[deg[i]].push_back(i); for(int i = 0; i < N; i++) { sort(edge[i].begin(), edge[i].end(), [] (int e, int f) { return deg[U[e]] + deg[V[e]] > deg[U[f]] + deg[V[f]]; }); } dfs1(0, -1); set<pii> it_list; for(int i = 0; i < N; i++) it_list.insert({-depth[i], i}); vll res(N, 0); res[0] = wt_sum; // root deg <= K-1 vll dp0(N), dp1(N); //root deg <= K DS extra_edges[N]; vi intdeg = deg; for(int i = 1; i < N; i++) intdeg[i]--; for(int k = 1; k < N; k++) { // cerr << "\n\n\n\n\n"; // cerr << "k = " << k << '\n'; for(int u: deg_occ[k]) //deg_occ[0] is empty { // cerr << "eliminating " << u << '\n'; it_list.erase({-depth[u], u}); for(int e : edge[u]) { int v = U[e] + V[e] - u; int w = W[e]; if(parent[v] != u) extra_edges[v].insert(w); // cerr << "extra edges " << v << " -> insert " << w << '\n'; } } for(auto p: it_list) { // cerr << "\n\n"; int u = p.second; // cerr << "u = " << u << '\n'; // cerr << "ee = "; // for(ll y : extra_edges[u].values) cerr << y << ' '; // cerr << '\n'; dp0[u] = dp1[u] = INF; ll basicCost = 0; vector<ll> upgrades; for(auto e: edge[u]) { int v = U[e] + V[e] - u; ll w = W[e]; if(v == parent[u]) continue; if(deg[v] <= k) break; basicCost += dp1[v]; upgrades.push_back(dp0[v] + w - dp1[v]); } sort(upgrades.begin(), upgrades.end()); ll upgrade_total = 0; dp0[u] = min(dp0[u], basicCost + extra_edges[u].minSum(intdeg[u] - k)); dp1[u] = min(dp1[u], basicCost + extra_edges[u].minSum(intdeg[u] - (k-1))); // cerr << "pre : " << dp0[u] << ' ' << dp1[u] << '\n'; // cerr << basicCost << '\n'; // cerr << "ee size = " << sz(extra_edges[u]) << ", query val = " << intdeg[u] - k << '\n'; for(int cct = 0; cct < sz(upgrades); cct++) { // cerr << "cct = " << cct << '\n'; upgrade_total += upgrades[cct]; dp0[u] = min(dp0[u], basicCost + upgrade_total + extra_edges[u].minSum(intdeg[u] - k - (cct+1))); dp1[u] = min(dp1[u], basicCost + upgrade_total + extra_edges[u].minSum(intdeg[u] - (k-1) - (cct+1))); // cerr << "! " << intdeg[u] - k - (cct+1) << ' ' << intdeg[u] - (k-1) - (cct+1) << '\n'; // cerr << cct << " , " << basicCost + upgrade_total + extra_edges[u].minSum(intdeg[u] - k - (cct+1)) << ' ' << basicCost + upgrade_total + extra_edges[u].minSum(intdeg[u] - (k-1) - (cct+1)) << '\n'; } if(u == 0) { // cerr << "adding " << dp0[u] << " a to res " << k << '\n'; res[k] += dp0[u]; } else if(deg[parent[u]] <= k) { // cerr << "adding " << min(dp1[u], dp0[u] + par_wt[u]) << " b to res " << k << '\n'; res[k] += min(dp1[u], dp0[u] + par_wt[u]); } // cerr << u << " : " << parent[u] << ' ' << dp0[u] << ' ' << dp1[u] << '\n'; } } return res; }
#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...