Cod sursa(job #3178151)

Utilizator juniorOvidiu Rosca junior Data 1 decembrie 2023 10:58:06
Problema Lowest Common Ancestor Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.67 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

ifstream fin("lca.in");
ofstream fout("lca.out");

const int NMAX = 100001;
const int LMAX = 17;

vector<vector<int>> arbore;
vector<int> niveluri, turEuler, primaAparitie, lg(NMAX);
int rmq[LMAX][2 * NMAX], n, m;

void dfs(int nodCurent, int nivelCurent) {
    primaAparitie[nodCurent] = turEuler.size();
    turEuler.push_back(nodCurent);
    niveluri.push_back(nivelCurent);

    for (int copil : arbore[nodCurent]) {
        dfs(copil, nivelCurent + 1);
        turEuler.push_back(nodCurent);
        niveluri.push_back(nivelCurent);
    }
}

void calculeazaRMQ() {
    for (int i = 0; i < turEuler.size(); i++)
        rmq[0][i] = turEuler[i];

    for (int i = 1; (1 << i) <= turEuler.size(); i++)
        for (int j = 0; j + (1 << i) <= turEuler.size(); j++)
            rmq[i][j] = min(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
}

int lca(int u, int v) {
    int start = primaAparitie[u], end = primaAparitie[v];
    if (start > end) swap(start, end);

    int lungime = end - start + 1;
    int k = lg[lungime];
    return min(rmq[k][start], rmq[k][end - (1 << k) + 1]);
}

int main() {
    fin >> n >> m;
    arbore.resize(n + 1);
    primaAparitie.resize(n + 1);

    for (int nod = 2, parinte; nod <= n; nod++) {
        fin >> parinte;
        arbore[parinte].push_back(nod);
    }

    dfs(1, 0);

    lg[1] = 0;
    for (int i = 2; i <= n; i++)
        lg[i] = lg[i / 2] + 1;

    calculeazaRMQ();

    for (int i = 0, u, v; i < m; i++) {
        fin >> u >> v;
        fout << lca(u, v) << '\n';
    }

    return 0;
}