Submission #1317544

#TimeUsernameProblemLanguageResultExecution timeMemory
1317544spetrTree (IOI24_tree)C++20
0 / 100
2097 ms40520 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long #define vl vector<long long> #define vll vector<vector<long long>> vll tree; vl weights; vl c; vl parents; vl w; vl subs; // Aktuální součet v podstromu (S[i]) long long query(int L, int R){ ll n = tree.size(); c.assign(n, 0); subs.assign(n, 0); // Sety: {váha, id_vrcholu}. Používáme multiset, kdyby měly vrcholy stejnou váhu, // ale set<pair> stačí, protože ID je unikátní. vector<set<pair<ll, ll>>> sets(n); // 1. Bottom-up průchod for (ll i = n - 1; i >= 0; i--){ // a) Přidáme aktuální vrchol do setu kandidátů sets[i].insert({w[i], i}); // Spočítáme aktuální S[i]. // Protože začínáme s C[i]=0, je S[i] rovno součtu S dětí. ll current_sum = 0; // b) Sloučení dětí (Small-to-Large Merging) int biggest_child = -1; size_t max_size = 0; // První průchod: najít nejtěžšího syna a sečíst S for (ll child : tree[i]){ if (child != parents[i]){ current_sum += subs[child]; if (sets[child].size() > max_size){ max_size = sets[child].size(); biggest_child = child; } } } // Přičteme vlastní C[i] (které je zatím 0, ale pro úplnost) subs[i] = current_sum + c[i]; // Swap s největším if (biggest_child != -1){ swap(sets[i], sets[biggest_child]); } // Dosypání ostatních for (ll child : tree[i]){ if (child != parents[i] && child != biggest_child){ for (auto &item : sets[child]){ sets[i].insert(item); } sets[child].clear(); } } // === FÁZE 1: Doplňování do L (pokud je součet moc malý) === while (subs[i] < L) { if (sets[i].empty()) break; // Nemělo by nastat pair<ll, ll> best = *sets[i].begin(); ll u = best.second; // Kolik potřebujeme přidat? ll need = L - subs[i]; // Validace cesty nahoru: Můžeme přidat, aniž bychom porušili R? // (Tato kontrola je nutná, pokud by přidání způsobilo, že nějaký potomek přeteče přes R. // Většinou ale doplňujeme "díru", takže to projde. Ale formálně:) ll limit_on_path = 2e18; ll curr = u; bool blocked = false; while (true){ // Kolik místa zbývá do R? if (subs[curr] >= R) { // Už jsme na hraně nebo přes blocked = true; break; } limit_on_path = min(limit_on_path, (ll)R - subs[curr]); if (curr == i) break; curr = parents[curr]; } if (blocked || limit_on_path == 0) { sets[i].erase(sets[i].begin()); // Tento vrchol už nemůžeme zvýšit continue; } ll k = min(need, limit_on_path); // Aplikace změny c[u] += k; curr = u; while(true){ subs[curr] += k; if (curr == i) break; curr = parents[curr]; } } // === FÁZE 2: Ořezávání na R (pokud je součet moc velký) === while (subs[i] > R){ if (sets[i].empty()) break; pair<ll, ll> best = *sets[i].begin(); ll u = best.second; ll need = subs[i] - R; // Validace cesty nahoru: Můžeme ubrat, aniž bychom podtekli pod L? ll limit_on_path = 2e18; ll curr = u; bool blocked = false; while (true){ if (subs[curr] <= L) { blocked = true; break; } limit_on_path = min(limit_on_path, subs[curr] - (ll)L); if (curr == i) break; curr = parents[curr]; } if (blocked || limit_on_path == 0) { sets[i].erase(sets[i].begin()); // Tento vrchol už nemůžeme snížit continue; } ll k = min(need, limit_on_path); c[u] -= k; curr = u; while(true){ subs[curr] -= k; if (curr == i) break; curr = parents[curr]; } } } ll price = 0; for (ll i = 0; i < n; i++){ price += w[i] * abs(c[i]); } return price; } void init(std::vector<int> P, std::vector<int> W){ weights.clear(); tree.clear(); parents.clear(); w.clear(); for (ll i = 0; i < W.size(); i++){ weights.push_back(W[i]); } tree.resize(P.size()); for (ll i = 1; i < P.size(); i++){ tree[i].push_back(P[i]); tree[P[i]].push_back(i); } for (ll i = 0; i < P.size(); i++){ parents.push_back(P[i]); w.push_back(W[i]); } }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...