Cod sursa(job #3124933)

Utilizator BuzdiBuzdugan Rares Andrei Buzdi Data 30 aprilie 2023 16:57:06
Problema Lowest Common Ancestor Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.81 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int NMAX = 1e5;
const int LOGMAX = 18;

int n, Q;

vector<int> Fii[NMAX + 1];
bool viz[NMAX + 1];
int Euler[2 * NMAX + 1], ind_E;
int Nivel[NMAX + 1];
int Pozitie[NMAX + 1];

int RMQ[NMAX + 1][LOGMAX];
int LOG[2 * NMAX + 1];

void DFS_Euler(int Nod, int Nivel_Curent)
{
    viz[Nod] = 1;
    Nivel[Nod] = Nivel_Curent;
    Euler[++ind_E] = Nod;
    Pozitie[Nod] = ind_E;

    for(int Fiu : Fii[Nod])
    {
        if(!viz[Fiu])
        {
            DFS_Euler(Fiu, Nivel_Curent + 1);
            Euler[++ind_E] = Nod;
        }
    }
}

void PreCalcRMQ()
{
    for(int i = 2; i <= ind_E; i++)
        LOG[i] = LOG[i / 2] + 1;

    for(int i = 1; i <= ind_E; i++)
        RMQ[i][0] = Euler[i];

    for(int k = 1; (1 << k) <= ind_E; k++)
        for(int i = 1; i + (1 << k) - 1 <= ind_E; i++)
        {
            int Nivel1 = Nivel[RMQ[i][k - 1]];
            int Nivel2 = Nivel[RMQ[i + (1 << (k - 1))][k - 1]];

            if(Nivel1 < Nivel2)
                RMQ[i][k] = RMQ[i][k - 1];
            else
                RMQ[i][k] = RMQ[i + (1 << (k - 1))][k - 1];
        }
}

int LCA(int x, int y)
{
    int PozitieX = Pozitie[x];
    int PozitieY = Pozitie[y];

    if(PozitieX > PozitieY)
        swap(PozitieX, PozitieY);

    int k = LOG[PozitieY - PozitieX + 1];
    return min(RMQ[PozitieX][k], RMQ[PozitieY - (1 << k) + 1][k]);
}

int main()
{
    cin >> n >> Q;
    for(int i = 2; i <= n; i++)
    {
        int x;
        cin >> x;
        Fii[x].push_back(i);
    }

    DFS_Euler(1, 1);
    PreCalcRMQ();

    while(Q--)
    {
        int x, y;
        cin >> x >> y;
        cout << LCA(x, y) << '\n';
    }

    return 0;
}