Submission #1241831

#TimeUsernameProblemLanguageResultExecution timeMemory
1241831nibertTree (IOI24_tree)C++20
0 / 100
2096 ms26344 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 200005; int N; vector<int> tree[MAXN]; int weight[MAXN]; bool isLeaf[MAXN]; // For Bottom-up int parent[MAXN]; // For Top-down struct Segment { ll a = 0, b = 0; }; vector<Segment> segments; void dfs_mark_leaves(int u) { isLeaf[u] = true; for (int v : tree[u]) { isLeaf[u] = false; dfs_mark_leaves(v); } } ll bottom_up_greedy(int L, int R) { vector<int> C(N, 0); vector<ll> sub_sum(N); for (int i = 0; i < N; ++i) { if (isLeaf[i]) C[i] = L; } for (int i = N - 1; i >= 0; --i) { sub_sum[i] += C[i]; if (parent[i] != -1) sub_sum[parent[i]] += sub_sum[i]; } priority_queue<pair<int, int>> pq; // max-heap by weight for (int i = 0; i < N; ++i) { if (C[i] > 0) pq.emplace(weight[i], i); } for (int i = N - 1; i >= 0; --i) { while (sub_sum[i] > R) { while (!pq.empty()) { int w = pq.top().first; int j = pq.top().second; pq.pop(); // check if reducing C[j] by 1 keeps all ancestor subtree sums >= L bool valid = true; int x = j; while (x != -1) { if (sub_sum[x] - 1 < L) { valid = false; break; } x = parent[x]; } if (valid) { C[j]--; x = j; while (x != -1) { sub_sum[x]--; x = parent[x]; } if (C[j] > 0) pq.emplace(weight[j], j); break; } } } } ll cost = 0; for (int i = 0; i < N; ++i) cost += 1LL * abs(C[i]) * weight[i]; return cost; } int leaf_count[MAXN]; int min_internal_weight; void dfs_count_leaves(int u) { if (isLeaf[u]) { leaf_count[u] = 1; return; } leaf_count[u] = 0; for (int v : tree[u]) { dfs_count_leaves(v); leaf_count[u] += leaf_count[v]; } } ll top_down_greedy(int u, int L, int R) { if (leaf_count[u] * L <= R) { return 1LL * L * leaf_count[u] * weight[u]; } if (isLeaf[u]) return 1LL * L * weight[u]; ll extra = (1LL * leaf_count[u] * L - R) * weight[u]; ll res = extra; for (int v : tree[u]) { res += top_down_greedy(v, L, R); } return res; } void init(vector<int> P, vector<int> W) { N = P.size(); for (int i = 0; i < N; ++i) { tree[i].clear(); isLeaf[i] = false; } for (int i = 1; i < N; ++i) { tree[P[i]].push_back(i); parent[i] = P[i]; } parent[0] = -1; for (int i = 0; i < N; ++i) weight[i] = W[i]; dfs_mark_leaves(0); dfs_count_leaves(0); min_internal_weight = INT_MAX; for (int i = 0; i < N; ++i) { if (!isLeaf[i]) min_internal_weight = min(min_internal_weight, weight[i]); } } ll query(int L, int R) { if (N <= 2000 || R - L <= 10 || R <= 10 || L == R || N <= 60'000) { return bottom_up_greedy(L, R); } return top_down_greedy(0, 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...