Submission #1317541

#TimeUsernameProblemLanguageResultExecution timeMemory
1317541spetrTree (IOI24_tree)C++20
13 / 100
2160 ms1600880 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long const ll mmod = 998244353; #define vl vector<long long> #define vll vector<vector<long long>> #define pl pair<long long, long long> #define vb vector<bool> vll tree; vl weights; vl c; vl parents; vl w; vl subs; // DFS už nepotřebujeme, nahradí ho set // pl dfs(ll v, ll p, ll l){ ... } long long query(int L, int R){ ll n = tree.size(); c.clear(); c.resize(n, 0); subs.clear(); subs.resize(n, 0); // Pole setů: každý index nese set kandidátů {váha, id_vrcholu} pro daný podstrom vector<set<pair<ll, ll>>> sets(n); // Inicializace listů for (ll i = 1; i < n; i++){ if (tree[i].size() == 1){ c[i] = L; subs[i] = L; } } // Bottom-up průchod for (ll i = n - 1; i >= 0; i--){ ll suma = subs[i]; // Začneme s tím, co tam je (pro listy L, jinak 0) // Přidáme aktuální vrchol do svého setu kandidátů sets[i].insert({w[i], i}); for (ll j = 0; j < tree[i].size(); j++){ ll child = tree[i][j]; if (child != parents[i]){ suma += subs[child]; // OPRAVA: přičítáme subs dítěte, ne j-tého prvku pole subs // "Hloupé" sloučení setů: prostě vše z dítěte nasypeme k rodiči for (auto p : sets[child]){ sets[i].insert(p); } } } subs[i] = suma; // Dokud je součet podstromu moc velký while (subs[i] > R){ if (sets[i].empty()) break; // Pojistka, nemělo by nastat pokud existuje řešení // Podíváme se na nejlevnější vrchol v podstromu pair<ll, ll> best = *sets[i].begin(); ll pos = best.second; // VALIDACE: Zkontrolujeme cestu nahoru k "i", zda můžeme odebírat bool is_valid = true; ll curr = pos; while (true) { if (subs[curr] <= L) { is_valid = false; break; } if (curr == i) break; curr = parents[curr]; } // Pokud vrchol není validní (někde na cestě bychom podtekli L), vyhodíme ho if (!is_valid) { sets[i].erase(sets[i].begin()); continue; } // Pokud validní je, zjistíme, o kolik můžeme snížit (k) ll k = subs[i] - R; // Maximálně o tolik, kolik přečuhujeme přes R curr = pos; while (true){ k = min(k, subs[curr] - L); // Omezíme tím, kolik chybí do L na cestě if (curr == i) break; curr = parents[curr]; } // Aplikujeme změnu c[pos] -= k; // Aktualizujeme součty na cestě nahoru k "i" curr = pos; while (true){ subs[curr] -= k; if (curr == i) break; curr = parents[curr]; } // Poznámka: Vrchol ze setu nevyhazujeme hned, protože možná půjde // v dalším kole snížit znovu. Vyhodí ho až validační check, // až narazí na hranu L. } } 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){ // Reset globálních proměnných pro případ vícenásobného volání testeru 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...