Cod sursa(job #3324015)

Utilizator apoputoaievladVlad Cristian Apoputoaie apoputoaievlad Data 20 noiembrie 2025 18:33:16
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.76 kb
#include <fstream>
#include <vector>

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

const int NMAX = 100005;
const int LOGMAX = 18;

vector<int> adj[NMAX];
vector<int> st;
int anc[NMAX][LOGMAX];
int Time, n;
int in[NMAX], out[NMAX];

void dfs(int nod, int t) {
    anc[nod][0] = t;
    for (int j = 1; true; j++) {
        // nod...2^(j-1)...anc[nod][j-1]...2^(j-1)...anc[nod][j]
        anc[nod][j] = anc[anc[nod][j - 1]][j - 1];

        if (anc[nod][j] == 0) {
            // am iesit din arbore
            break;
        }
    }

    in[nod] = ++Time;
    for (auto i: adj[nod]) {
        dfs(i, nod);
    }
    out[nod] = Time;
}

int getAnc(int nod, int k) {
    // iau fiecare bit care este setat
    // si fac un salt de dimensiune 2^bit
    // la final o sa il am pe k, compus din
    // puteri de 2 distincte
    for (int i = 0; (1 << i) <= k; i++) {
        if (k & (1 << i)) {
            nod = anc[nod][i];
        }
    }

    return nod;
}

bool isAncestor(int a, int b) {
    if (a == 0) {
        return true;
    }
    return in[a] <= in[b] && out[b] <= out[a];
}

int lca(int a, int b) {
    int st = 0, dr = n, ans = n;

    while (st <= dr) {
        int m = (st + dr) / 2;

        if (isAncestor(getAnc(a, m), b)) {
            ans = m;
            dr = m - 1;
        } else {
            st = m + 1;
        }
    }

    return getAnc(a, ans);
}

int main() {
    int q;
    cin >> n >> q;

    for (int i = 2; i <= n; i++) {
        int nod; cin >> nod;

        if (nod != 0) {
            adj[nod].push_back(i);
        }
    }

    dfs(1, 0);

    for (int i = 1; i <= q; i++) {
        int a, b; cin >> a >> b;

        cout << lca(a, b) << '\n';
    }
}