Editorial for Goblins


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Approach

The superiors form a tree rooted at goblin 0. For a query at goblin x, start at x's parent and walk toward the root, subtracting each goblin's power from Indra's budget p, counting how many superiors can be defeated before the next one would exceed the remaining budget.

A naive walk is too slow for n, q \le 10^5. Precompute binary lifting tables:

  • up[v][j]: the 2^j-th superior of v (or nonexistent)
  • jump\_sum[v][j]: the sum of powers of the 2^j goblins starting at v and walking up

Then each query greedily takes the largest jumps whose power sum fits in the remaining budget. This answers every query in O(\log n) after O(n \log n) preprocessing.

Solution (C++)

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n, q;
    long long indra;
    cin >> n >> q >> indra;

    vector<long long> power(n);
    for (int i = 0; i < n; i++) {
        cin >> power[i];
    }

    vector<vector<int> > adj(n);
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }

    vector<int> parent(n, -1);
    stack<int> st;
    st.push(0);
    parent[0] = -2;
    while (!st.empty()) {
        int v = st.top();
        st.pop();
        for (size_t i = 0; i < adj[v].size(); i++) {
            int to = adj[v][i];
            if (parent[to] != -1) {
                continue;
            }
            parent[to] = v;
            st.push(to);
        }
    }
    parent[0] = -1;

    const int LOGN = 18;
    const long long INF = (1LL << 62);
    vector<vector<int> > up(n, vector<int>(LOGN, -1));
    vector<vector<long long> > jump_sum(n, vector<long long>(LOGN, INF));

    for (int i = 0; i < n; i++) {
        up[i][0] = parent[i];
        jump_sum[i][0] = power[i];
    }
    for (int j = 1; j < LOGN; j++) {
        for (int i = 0; i < n; i++) {
            int mid = up[i][j - 1];
            if (mid == -1) {
                up[i][j] = -1;
                jump_sum[i][j] = INF;
            } else {
                up[i][j] = up[mid][j - 1];
                if (jump_sum[i][j - 1] > INF / 2 || jump_sum[mid][j - 1] > INF / 2) {
                    jump_sum[i][j] = INF;
                } else {
                    jump_sum[i][j] = jump_sum[i][j - 1] + jump_sum[mid][j - 1];
                }
            }
        }
    }

    for (int qi = 0; qi < q; qi++) {
        int at;
        cin >> at;
        int v = parent[at];
        long long budget = indra;
        int ans = 0;
        for (int j = LOGN - 1; j >= 0; j--) {
            if (v == -1) {
                break;
            }
            if (jump_sum[v][j] <= budget) {
                budget -= jump_sum[v][j];
                ans += 1 << j;
                v = up[v][j];
            }
        }
        cout << ans << "\n";
    }
}

Comments

There are no comments at the moment.