Editorial for Elders


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 (v, k), walk k steps toward the root from v. If k is larger than the depth of v, the answer is -1.

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). Then each query decomposes k into bits and jumps in O(\log n) after O(n \log n) preprocessing. Overall time is O((n + q) \log n).

Solution (C++)

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

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

    int n, q;
    cin >> n >> q;

    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);
    vector<int> depth(n, 0);
    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;
            depth[to] = depth[v] + 1;
            st.push(to);
        }
    }
    parent[0] = -1;

    const int LOGN = 18;
    vector<vector<int> > up(n, vector<int>(LOGN, -1));
    for (int i = 0; i < n; i++) {
        up[i][0] = parent[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;
            } else {
                up[i][j] = up[mid][j - 1];
            }
        }
    }

    for (int qi = 0; qi < q; qi++) {
        int v;
        long long k;
        cin >> v >> k;
        if (k > depth[v]) {
            cout << -1 << "\n";
            continue;
        }
        for (int j = 0; j < LOGN; j++) {
            if ((k >> j) & 1LL) {
                v = up[v][j];
            }
        }
        cout << v << "\n";
    }
}

Comments

There are no comments at the moment.