Submission #1200233

#TimeUsernameProblemLanguageResultExecution timeMemory
1200233rxlfd314Designated Cities (JOI19_designated_cities)C++20
100 / 100
1093 ms32624 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; using ari2 = array<int, 2>; using ari3 = array<int, 3>; using arl2 = array<ll, 2>; using arl3 = array<ll, 3>; template <class T> using vt = vector<T>; #define all(x) begin(x), end(x) #define size(x) (int((x).size())) #define REP(a,b,c,d) for(int a=(b);(d)>0?a<=(c):a>=(c);a+=(d)) #define FOR(a,b,c) REP(a,b,c,1) #define ROF(a,b,c) REP(a,b,c,-1) signed main() { #ifndef DEBUG ios_base::sync_with_stdio(false); cin.tie(nullptr); #endif int N; cin >> N; vt<vt<ari3>> adj(N); ll sum = 0; FOR(_, 2, N) { int a, b, c, d; cin >> a >> b >> c >> d, a--, b--; adj[a].push_back({b, c, d}); adj[b].push_back({a, d, c}); sum += c + d; } vt<ll> ans(N+1); /* 1 resort city */ { vt<ll> dp(N); auto dfs = [&](auto &&self, const int i, const int p) -> void { for (const auto &[j, c, d] : adj[i]) { if (j == p) continue; self(self, j, i); dp[i] += dp[j] + d; } }; dfs(dfs, 0, -1); auto reroot = [&](auto &&self, const int i, const int p) -> void { ans[1] = max(ans[1], dp[i]); for (const auto &[j, c, d] : adj[i]) { if (j == p) continue; dp[i] -= dp[j] + d; dp[j] += dp[i] + c; self(self, j, i); dp[j] -= dp[i] + c; dp[i] += dp[j] + d; } }; reroot(reroot, 0, -1); } /* >1 resort city */ { vt<int> szs(N), dead(N); auto dfs_szs = [&](auto &&self, const int i, const int p) -> void { szs[i] = 1; for (const auto &[j, c, d] : adj[i]) { if (dead[j] || j == p) continue; self(self, j, i); szs[i] += szs[j]; } }; auto centroid = [&](int i) { int p = -1; const int n = szs[i]; bool flag = true; while (flag) { flag = false; for (const auto &[j, c, d] : adj[i]) { if (j == p || dead[j]) continue; if (2 * szs[j] > n) { p = i; i = j; flag = true; break; } } } return i; }; vt<int> parent(N), best(N), nodes; vt<ll> depth(N), subtree(N); auto dfs_par = [&](auto &&self, const int i, const int p) -> ll { parent[i] = p; best[i] = i; subtree[i] = 0; nodes.push_back(i); for (const auto &[j, c, d] : adj[i]) { if (dead[j] || j == p) continue; depth[j] = depth[i] + c; subtree[i] += self(self, j, i) + d; if (depth[best[i]] < depth[best[j]]) best[i] = best[j]; } return subtree[i]; }; vt<int> seen(N); auto decomp = [&](auto &&self, const int root, const ll add) -> void { dfs_szs(dfs_szs, root, -1); const int cent = centroid(root); depth[cent] = 0; const ll have = dfs_par(dfs_par, cent, -1); if (size(nodes) == 1) return; sort(all(adj[cent]), [&](const ari3 &a, const ari3 &b) { return depth[best[a[0]]] > depth[best[b[0]]]; }); priority_queue<pair<ll, int>> pq; auto yeet = [&](int i) { for (; i >= 0 && !seen[i]; i = parent[i]) { seen[i] = 1; for (const auto &[j, c, d] : adj[i]) if (!seen[j] && !dead[j] && j != parent[i]) pq.push({depth[best[j]] - depth[i], best[j]}); } }; int cnt = 0; ll tot = have + add; for (int i = 0; i < size(adj[cent]) && cnt < 2; i++) { if (dead[adj[cent][i][0]]) continue; yeet(best[adj[cent][i][0]]); tot += depth[best[adj[cent][i][0]]]; cnt++; } ans[2] = max(ans[2], tot); while (size(pq)) { const auto [v, i] = pq.top(); pq.pop(); if (seen[i]) continue; cnt++, tot += v; ans[cnt] = max(ans[cnt], tot); yeet(i); } for (const auto &i : nodes) { seen[i] = 0; } nodes.clear(); dead[cent] = 1; for (const auto &[j, c, d] : adj[cent]) if (!dead[j]) self(self, j, subtree[cent] - subtree[j] - d + c + add); }; decomp(decomp, 0, 0); } FOR(i, 1, N) ans[i] = max(ans[i], ans[i-1]); int Q; cin >> Q; while (Q--) { int v; cin >> v; cout << sum - ans[v] << '\n'; } }
#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...