Submission #1241110

#TimeUsernameProblemLanguageResultExecution timeMemory
1241110hugo_pmTree (IOI24_tree)C++20
59 / 100
2096 ms30772 KiB
#include "tree.h" #include <cassert> #include <set> #include <iostream> #define int long long using i32 = int32_t; using namespace std; struct MyVec { vector<int> vals, suff_sum; int N; MyVec(const vector<int> &_v) : vals(_v), N(_v.size()) { sort(vals.begin(), vals.end()); suff_sum.resize(vals.size() + 1); for (int i = N-1; i >= 0; --i) { suff_sum[i] = vals[i] + suff_sum[i+1]; } } /// returns {sum, count} of values >= target pair<int, int> sum_geq(int target) { int i = lower_bound(vals.begin(), vals.end(), target) - vals.begin(); return {suff_sum[i], N - i}; } }; int N; vector<int> parent, weight; vector<vector<int>> children; namespace St45 { bool active = true; // set to false in init int sum_weight_real_leaves = 0; MyVec tool({}); void prepare() { vector<bool> seen(N); vector<int> sub_leaves; for (int subroot = 0; subroot < N; ++subroot) { if (children[subroot].empty()) sum_weight_real_leaves += weight[subroot]; if (weight[subroot] > 0 && !seen[subroot]) { sub_leaves.push_back(0); vector<int> stk { subroot }; while (!stk.empty()) { int cur = stk.back(); stk.pop_back(); seen[cur] = true; if (weight[cur] == 0 || children[cur].empty()) { ++sub_leaves.back(); } else { for (int child : children[cur]) { stk.push_back(child); } } } } } tool = MyVec(sub_leaves); } int solve(int L, int R) { // int ans = L*real_leaves; // for (int x : tool.vals) // ans += max(L*x - R, 0ll); // return ans; auto [sum_above, cnt_above] = tool.sum_geq((R+L-1)/L); // ? return L*sum_weight_real_leaves + L*sum_above - R*cnt_above; } } void init(vector<i32> _P, vector<i32> _W) { parent = vector<int>(_P.begin(), _P.end()); weight = vector<int>(_W.begin(), _W.end()); N = (int)parent.size(); children.resize(N); for (int node = 1; node < N; ++node) { children[parent[node]].push_back(node); } for (int w : weight) { if (w > 1) St45::active = false; } if (St45::active) St45::prepare(); } struct Helper { int cost, stock; auto operator<=>(const Helper&) const = default; }; class MyPq { friend MyPq* merge(MyPq*, MyPq*); public: void clear() { helpers.clear(); sum_stock = 0; } void push(int cost, int stock) { if (stock == 0) return; helpers.insert({cost, stock}); sum_stock += stock; } void trim(int lim_sum) { if (sum_stock > lim_sum) { consume(sum_stock - lim_sum, true); assert(sum_stock == lim_sum); } } int cheap_help(int target) { return consume(target, false); } private: int consume(int target, bool worst) { int cur_cost = 0; while (target > 0) { assert(!helpers.empty()); auto it = worst ? prev(helpers.end()) : helpers.begin(); Helper nxt = *it; helpers.erase(it); int taking = min(target, nxt.stock); target -= taking; sum_stock -= taking; nxt.stock -= taking; cur_cost += taking * nxt.cost; if (nxt.stock) helpers.insert(nxt); } return cur_cost; } multiset<Helper> helpers; int sum_stock = 0; }; MyPq* merge(MyPq* small, MyPq* large) { if (small->helpers.size() > large->helpers.size()) swap(small, large); for (const Helper &h : small->helpers) large->push(h.cost, h.stock); small->clear(); return large; } int solve(int L, int R) { vector<MyPq> block_allocation(N); vector<MyPq*> dp(N); /// not always up to date! vector<int> tmp_sum_subtree(N); for (int i = 0; i < N; ++i) { dp[i] = &block_allocation[i]; } int answer = 0; for (int node = N-1; node >= 0; --node) { int &cur_sum = tmp_sum_subtree[node]; if (children[node].empty()) { answer += weight[node] * L; cur_sum = L; continue; } MyPq* &cur = dp[node]; for (int child : children[node]) { cur = merge(cur, dp[child]); dp[child] = nullptr; cur_sum += tmp_sum_subtree[child]; } cur->push(weight[node], cur_sum - L); if (cur_sum > R) { answer += cur->cheap_help(cur_sum - R); cur_sum = R; } cur->trim(cur_sum - L); } return answer; } long long query(i32 L, i32 R) { if (St45::active) return St45::solve(L, R); return solve(L, R); }
#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...