제출 #1290025

#제출 시각아이디문제언어결과실행 시간메모리
1290025TymondDesignated Cities (JOI19_designated_cities)C++20
100 / 100
347 ms50464 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; using ld = long double; #define fi first #define se second #define vi vector<int> #define vll vector<long long> #define pii pair<int, int> #define pll pair<long long, long long> #define pb push_back #define mp make_pair #define eb emplace_back #define all(x) (x).begin(), (x).end() #define sz(x) (int)(x).size() mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); mt19937_64 rng64(chrono::high_resolution_clock::now().time_since_epoch().count()); inline int rand(int l,int r){return uniform_int_distribution<int>(l, r)(rng);} inline ll rand(ll l,ll r){return uniform_int_distribution<ll>(l, r)(rng64);} #ifdef DEBUG auto&operator<<(auto&o,pair<auto,auto>p){return o<<"("<<p.first<<", "<<p.second<<")";} auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<<e;return o<<"}";} #define debug(X...)cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(X) #else #define debug(...){} #endif struct custom_hash { static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } }; struct pair_hash{ size_t operator()(const pair<int,int>&x)const{ return hash<long long>()(((long long)x.first)^(((long long)x.second)<<32)); } }; struct Node{ ll best, lazy; int bestId; Node(){ best = lazy = 0LL; bestId = 0; } Node(ll b1, ll l, int b2){ best = b1; lazy = l; bestId = b2; } }; const int MAXN = 2e5 + 7; const int BASE = (1 << 18); Node tree[2 * BASE + 7]; vector<pair<int, pii>> g[MAXN]; ll goingUp[MAXN]; ll sumForOne[MAXN]; int in[MAXN]; int inF[MAXN]; int out[MAXN]; int parent[MAXN]; int used[MAXN]; ll A[MAXN]; ll jumpUp[MAXN]; ll ans[MAXN]; ll sum; int n, q, timer; ll now; pii best; void dfsInit(int v, int p){ for(auto ele : g[v]){ if(ele.fi == p){ continue; } jumpUp[ele.fi] = ele.se.fi; goingUp[v] += ele.se.se; dfsInit(ele.fi, v); goingUp[v] += goingUp[ele.fi]; } } void dfs1(int v, int p, ll up = 0LL){ sumForOne[v] = goingUp[v] + up; for(auto ele : g[v]){ if(ele.fi == p){ continue; } dfs1(ele.fi, v, up + goingUp[v] - goingUp[ele.fi] - ele.se.se + ele.se.fi); } } void dfs2(int v, int p, ll up = 0LL){ A[v] = up; used[v] = 0; parent[v] = p; in[v] = timer++; inF[in[v]] = v; for(auto ele : g[v]){ if(ele.fi == p){ continue; } jumpUp[ele.fi] = ele.se.fi; dfs2(ele.fi, v, up + ele.se.fi); } out[v] = timer - 1; } Node merge(Node& a, Node& b){ if(a.best >= b.best){ return Node(a.best, 0LL, a.bestId); } return Node(b.best, 0LL, b.bestId); } void Push(int v){ for(int j = 0; j < 2; j++){ tree[2 * v + j].lazy += tree[v].lazy; tree[2 * v + j].best += tree[v].lazy; } tree[v].lazy = 0LL; } void upd(int v, int l, int p, int a, int b, ll val){ if(p < a || b < l){ return; } if(a <= l && p <= b){ tree[v].best += val; tree[v].lazy += val; return; } Push(v); int mid = (l + p) / 2; upd(2 * v, l ,mid, a, b, val); upd(2 * v + 1, mid + 1, p, a,b, val); tree[v] = merge(tree[2 * v], tree[2 * v + 1]); } void dfsRecalc(int v, int p){ if(v != p && !used[v]){ A[v] = jumpUp[v] + A[p]; } for(auto ele : g[v]){ if(ele.fi != p){ dfsRecalc(ele.fi, v); } } } pair<ll, int> dfsPair(int v, int p){ pair<pair<ll, int>, pair<ll, int>> e = mp(mp(0LL, v), mp(-1LL, -1)); for(auto ele : g[v]){ if(ele.fi == p){ continue; } pair<ll, int> x = dfsPair(ele.fi, v); if(x.fi >= e.fi.fi){ swap(e.fi, e.se); e.fi = x; }else if(x.fi > e.se.fi){ e.se = x; } } // debug(v); // debug(e); // debug(jumpUp[v]); if(e.se.fi == -1LL){ e.fi.fi += jumpUp[v]; return e.fi; } if(now < sumForOne[v] + e.fi.fi + e.se.fi){ now = sumForOne[v] + e.fi.fi + e.se.fi; best = mp(e.fi.se, e.se.se); } e.fi.fi += jumpUp[v]; return e.fi; } int main(){ ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL); cin >> n; for(int i = 1; i < n; i++){ int a, b, c, d; cin >> a >> b >> c >> d; g[a].pb(mp(b, mp(c, d))); g[b].pb(mp(a, mp(d, c))); sum += (c + d); } //policz wynik int root; dfsInit(1, 1); dfs1(1, 1); root = 1; for(int i = 2; i <= n; i++){ if(sumForOne[i] > sumForOne[root]){ root = i; } } ans[1] = sumForOne[root]; //teraz znajdź rozw dla e = 2 now = 0LL; best = mp(-1, -1); dfsPair(1, 1); ans[2] = now; // debug(best); root = best.fi; timer = 0; dfs2(root, root); while(best.se != root){ used[best.se] = 1; A[best.se] = 0LL; best.se = parent[best.se]; } dfsRecalc(root, root); for(int i = 1; i <= n; i++){ tree[in[i] + BASE] = Node(A[i], 0LL, i); } for(int i = BASE - 1; i >= 1; i--){ tree[i] = merge(tree[2 * i], tree[2 * i + 1]); } used[root] = 1; for(int i = 3; i <= n; i++){ ans[i] = ans[i - 1] + tree[1].best; int v = tree[1].bestId; ll curr = tree[1].best; int pre = -1; while(!used[v]){ used[v] = 1; //aktualizuj drzewo upd(1, 0, BASE - 1, in[v], out[v], -curr); if(pre != -1){ upd(1, 0, BASE - 1, in[pre], out[pre], curr); } curr -= jumpUp[v]; pre = v; v = parent[v]; } } cin >> q; while(q--){ int e; cin >> e; cout << (ll)sum - ans[e] << '\n'; } 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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...