Submission #1239825

#TimeUsernameProblemLanguageResultExecution timeMemory
1239825hugo_pmTree (IOI24_tree)C++20
41 / 100
2097 ms30536 KiB
#include "tree.h"
#include <cassert>
#include <set>
#define int long long
using i32 = int32_t;
using namespace std;

int N;
vector<int> parent, weight;
vector<vector<int>> children;

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);
    }
}

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) {
    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...