Cod sursa(job #3308972)

Utilizator Iustin_Mircea2010Iustin Mircea Iustin_Mircea2010 Data 30 august 2025 15:03:30
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.09 kb
#include <bits/stdc++.h>

using namespace std;

int h[100005], arb[100005], head[100005], parent[100005], heavyson[100005];
vector<int> child[100005];
int currchain;
int chain[100005];
int binlift[5][100005], lvlchain[100005], chainspar[100005];

void dfs(int u) {
    arb[u] = 1;
    for (int v : child[u]) {
        dfs(v);
        arb[u] += arb[v];
        if (arb[v] > arb[heavyson[u]]) {
            heavyson[u] = v;
        }
    }
}

void decomp(int u, bool newchain = 1, int chainpar = 0) {
    if (newchain) {
        chain[u] = ++currchain;
        chainspar[chain[u]] = u;
        head[u] = u;
        binlift[0][chain[u]] = chainpar;
        lvlchain[chain[u]] = lvlchain[chainpar] + 1;
    }
    else {
        head[u] = head[parent[u]];
        chain[u] = chain[parent[u]];
    }
    for (int v : child[u]) {
        if (v == heavyson[u]) {
            decomp(v, 0, 0);
        }
        else
            decomp(v, 1, chain[u]);
    }
}

void build() {
    for (int b = 1; (1 << b) < currchain; b++) {
        for (int i = 1; i <= currchain; i++) {
            binlift[b][i] = binlift[b - 1][binlift[b - 1][i]];
        }
    }
}

int solve(int u, int v) {
    int chainu = chain[u], chainv = chain[v];
    if (chainu == chainv) {
        //returnez nodul de mai sus
        return h[u] < h[v] ? u : v;
    }
    if (lvlchain[chainu] > lvlchain[chainv]) {
        int dif = lvlchain[chainu] - lvlchain[chainv] - 1;
        for (int b = 0; b < 5; b++) {
            if (dif & (1 << b)) {
                chainu = binlift[b][chainu];
            }
        }
        if (binlift[0][chainu] == chainv) {
            u = parent[chainspar[chainu]];
            return h[u] < h[v] ? u : v;
        }
        chainu = binlift[0][chainu];
    }
    else if (lvlchain[chainv] > lvlchain[chainu]) {
        int dif = lvlchain[chainv] - lvlchain[chainu] - 1;
        for (int b = 0; b < 5; b++) {
            if (dif & (1 << b)) {
                chainv = binlift[b][chainv];
            }
        }
        if (binlift[0][chainv] == chainu) {
            v = parent[chainspar[chainv]];
            return h[u] < h[v] ? u : v;
        }
        chainv = binlift[0][chainv];
    }
    for (int b = 0; b < 5; b++) {
        if (binlift[b][chainu] != binlift[b][chainv]) {
            chainu = binlift[b][chainu];
            chainv = binlift[b][chainv];
        }
    }
    u = parent[chainspar[chainu]];
    v = parent[chainspar[chainv]];
    return h[u] < h[v] ? u : v;
}

int main() {

    ifstream cin("lca.in");
    ofstream cout("lca.out");

    int n, q;
    cin >> n >> q;
    h[1] = 1;
    for (int i = 2; i <= n; i++) {
        int a;
        cin >> a;
        parent[i] = a;
        child[a].push_back(i);
        h[i] = h[a] + 1;
    }
    dfs(1);
    decomp(1);
    build();
    //cout << chain[10] << " " << chain[3] << '\n';
    //cout << lvlchain[chain[10]] << " " << lvlchain[chain[11]] << binlift[0][6] << '\n';
    while (q--) {
        int u, v;
        cin >> u >> v;
        cout << solve(u, v) << '\n';
    }
    return 0;
}