제출 #794901

#제출 시각아이디문제언어결과실행 시간메모리
794901PurpleCrayonDesignated Cities (JOI19_designated_cities)C++17
100 / 100
962 ms40912 KiB
#include <bits/stdc++.h> using namespace std; #define sz(v) int(v.size()) #define ar array typedef long long ll; const int N = 2e5+10, MOD = 1e9+7; const ll INF = 1e18+10; int n; vector<ar<int, 3>> adj[N]; ll ans[N]; ll calc_one(int c, int p) { ll sum = 0; for (auto [nxt, w, _] : adj[c]) if (nxt != p) { sum += w + calc_one(nxt, c); } return sum; } void dfs1(int c, int p, ll x) { ans[1] = min(ans[1], x); for (auto [nxt, a, b] : adj[c]) if (nxt != p) { dfs1(nxt, c, x - a + b); } } int sub[N]; bool blocked[N]; int dfs_sub(int c, int p) { sub[c] = 1; for (auto [nxt, x, y] : adj[c]) if (nxt != p && !blocked[nxt]) { sub[c] += dfs_sub(nxt, c); } return sub[c]; } int dfs_cent(int c, int p, int cnt) { for (auto [nxt, x, y] : adj[c]) if (nxt != p && !blocked[nxt] && sub[nxt] > cnt / 2) return dfs_cent(nxt, c, cnt); return c; } pair<ll, int> dfs_best(int c, int p, ll x) { pair<ll, int> best{x, c}; for (auto [nxt, w, _] : adj[c]) if (!blocked[nxt] && nxt != p) { best = max(best, dfs_best(nxt, c, x + w)); } return best; } vector<int> roots; int process(int c) { if (sz(adj[c]) == 1) roots.push_back(c); // can't hurt, and probably useful ll best_w = -1; int best_nxt = -1, best_c = -1; for (auto [nxt, w, _] : adj[c]) if (!blocked[nxt]) { auto cur = dfs_best(nxt, c, w); if (cur.first > best_w) { best_w = cur.first; best_nxt = nxt; best_c = cur.second; } } if (best_c != -1) { roots.push_back(best_c); } return best_nxt; } void build(int c) { if (c == -1) return; int cnt = dfs_sub(c, -1); int cent = dfs_cent(c, -1, cnt); int nxt = process(cent); blocked[cent] = 1; build(nxt); } int par[N], par_w[N]; ll sum[N]; bool marked[N]; void dfs_root(int c, int p) { par[c] = p; for (auto [nxt, w, _] : adj[c]) if (nxt != p) { par_w[nxt] = w; sum[nxt] = sum[c] + w; dfs_root(nxt, c); } } void add(int root) { sum[root] = par_w[root] = 0; dfs_root(root, -1); auto get_cost = [&](vector<int> p) { memset(marked, 0, sizeof(marked)); vector<ll> cost(n); for (int c : p) { int cur = c; while (cur != -1 && !marked[cur]) { marked[cur] = 1; cost[c] += par_w[cur]; cur = par[cur]; } } return cost; }; vector<int> p(n); iota(p.begin(), p.end(), 0); sort(p.begin(), p.end(), [&](int x, int y) { return sum[x] > sum[y]; }); auto base_cost = get_cost(p); sort(p.begin(), p.end(), [&](int x, int y) { return base_cost[x] > base_cost[y]; }); auto real_cost = get_cost(p); ll cur = accumulate(par_w, par_w + n, 0LL); sort(real_cost.rbegin(), real_cost.rend()); int cnt = 1; for (ll x : real_cost) { cur -= x; cnt++; ans[cnt] = min(ans[cnt], cur); } assert(cur == 0); } void solve() { cin >> n; for (int i = 0; i < n-1; i++) { int a, b; cin >> a >> b, --a, --b; int x, y; cin >> x >> y; adj[a].push_back({b, x, y}); adj[b].push_back({a, y, x}); } fill(ans, ans + n, INF); ll cost_one = calc_one(0, -1); dfs1(0, -1, cost_one); build(0); assert(sz(roots) <= 40); sort(roots.begin(), roots.end()); roots.resize(unique(roots.begin(), roots.end()) - roots.begin()); for (int c : roots) add(c); int q; cin >> q; while (q--) { int x; cin >> x; cout << ans[x] << '\n'; } } int main() { ios::sync_with_stdio(false); cin.tie(0); int T = 1; // cin >> T; while (T--) solve(); }
#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...