Cod sursa(job #3178513)

Utilizator juniorOvidiu Rosca junior Data 1 decembrie 2023 20:31:14
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.6 kb
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <vector>

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(2 * 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 d_rmq(int i) {
    for (int j = 0; j <= turEuler.size() - 1; j++)
        cout << setw(2) << rmq[i][j] << ' ';
    cout << endl;
}

void calculeazaRMQ() {
    for (int i = 0; i < turEuler.size(); i++)
        rmq[0][i] = i;
    for (int i = 1; (1 << i) <= turEuler.size(); i++) {
        for (int j = 0; j + (1 << i) <= turEuler.size(); j++) {
            int opt1 = rmq[i - 1][j];
            int opt2 = rmq[i - 1][j + (1 << (i - 1))];
            rmq[i][j] = (niveluri[opt1] < niveluri[opt2]) ? opt1 : opt2;
        }
        // cout << "rmq " << i << " \n";
        // d_rmq(i);
    }
}

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];
    int opt1 = rmq[k][start];
    int opt2 = rmq[k][end - (1 << k) + 1];
    if (niveluri[opt1] < niveluri[opt2])
        return turEuler[opt1];
    else
        return turEuler[opt2];
}

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);

    #pragma region d
    // for (int i = 0; i < turEuler.size(); i++)
    //     cout << setw(2) << i << ' ';
    // cout << '\n';
    // for (int nod : turEuler)
    //     cout << setw(2) << nod << ' ';
    // cout << '\n';
    // for (int nivel : niveluri)
    //     cout << setw(2) << nivel << ' ';
    // cout << '\n';
    // for (int loc : primaAparitie)
    //     cout << setw(2) << loc << ' ';
    // cout << '\n';
    #pragma endregion d

    lg[1] = 0;
    for (int i = 2; i <= turEuler.size(); 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;
}