Cod sursa(job #2648553)

Utilizator sebimihMihalache Sebastian sebimih Data 11 septembrie 2020 14:06:00
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.4 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

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

const int N = 100005;
const int LOG = 17;

int n, q;
int anc[LOG][N], d[N];

void computeDepth(int x)
{
    if (anc[0][x] == 0 || d[x])
        return;

    if (d[anc[0][x]] == 0 && anc[0][x] != 0)
        computeDepth(anc[0][x]);

    d[x] = d[anc[0][x]] + 1;

}

void precompute()
{
    for (int i = 1; i <= n; i++)
        computeDepth(i);

    for (int lvl = 1; (1 << lvl) <= n; lvl++)
        for (int i = 1; i <= n; i++)
            anc[lvl][i] = anc[lvl - 1][anc[lvl - 1][i]];
}

int solveQuery(int x, int y)
{
    if (d[x] < d[y])
        swap(x, y);

    // aducerea pe acelasi nivel
    int dif = d[x] - d[y];
    for (int lvl = 0; (1 << lvl) <= n; lvl++)
        if (dif & (1 << lvl))
            x = anc[lvl][x];

    // gasesc stramosul comun
    if (x == y)
        return x;
    for (int lvl = LOG - 1; lvl >= 0; lvl--)
        if (anc[lvl][x] != anc[lvl][y])
        {
            x = anc[lvl][x];
            y = anc[lvl][y];
        }
    return anc[0][x];
}

int main()
{
    fin >> n >> q;
    for (int i = 2; i <= n; i++)
        fin >> anc[0][i];

    precompute();
    while (q--)
    {
        int x, y;
        fin >> x >> y;
        fout << solveQuery(x, y) << '\n';
    }
    return 0;
}