Editorial for Goblins


Approach

The superiors form a tree rooted at goblin 00. For a query at goblin xx, start at xx's parent and walk toward the root, subtracting each goblin's power from Indra's budget pp, 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≤105n, q \le 10^5. Precompute binary lifting tables:

  • up[v][j]up[v][j]: the 2j2^j-th superior of vv (or nonexistent)
  • jump_sum[v][j]jump\_sum[v][j]: the sum of powers of the 2j2^j goblins starting at vv 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)O(\log n) after O(nlog⁡n)O(n \log n) preprocessing.

Solution (C++)

Code 1
#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";
    }
}

Comments0


No comments yet

Be the first to comment.

New comment


Log in to join the discussion.