Cod sursa(job #3321995)

Utilizator Lex._.Lex Guiman Lex._. Data 12 noiembrie 2025 09:08:40
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.61 kb
#include <bits/stdc++.h>
#define NMAX 100001
#define LOG 20
using namespace std;

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

vector<int> fii[NMAX];
int nivel[NMAX]; ///nivelul fiecarui nod

int lg[NMAX*2]; ///logaritmul fiecarui numar
int rmq[LOG][NMAX*2]; ///rmq pe reprezentarea euler a arborelui
int prima[NMAX*2]; ///prima aparitie a fiecarui nod in reprezentarea euler a arborelui

int cnt=0;
void dfs(int nod) ///calculam nivelul fiecarui nod si reprezentarea euler a arborelui
{
    rmq[0][++cnt]=nod;
    prima[nod]=cnt;
    for(auto& fiu : fii[nod])
    {
        nivel[fiu]=1+nivel[nod];
        dfs(fiu);
        rmq[0][++cnt]=nod;
    }
}

int min_nivel(int nod1, int nod2)
{
    if(nivel[nod1]<nivel[nod2]) return nod1;
    else return nod2;
}

void precalc() ///precalculeaza rmq
{
    for(int i=2; i<=cnt; i++) lg[i]=lg[i>>1]+1;

    for(int e=1; (1<<e)<=cnt; e++)
    {
        for(int i=1; i<=cnt-e; i++)
            rmq[e][i]=min_nivel(rmq[e-1][i], rmq[e-1][i+(1<<(e-1))]);
    }
}

int lca(int nod1, int nod2)
{
    int poz1=prima[nod1], poz2=prima[nod2];
    if(poz1>poz2)
    {
        swap(nod1, nod2);
        swap(poz1, poz2);
    }
    int dif=poz2-poz1+1;
    int e=lg[dif];
    return min_nivel(rmq[e][poz1], rmq[e][poz2-(1<<e)+1]);
}

int main()
{
    int n, m;
    in >> n >> m;
    for(int i=2; i<=n; i++)
    {
        int tata;
        in >> tata;
        fii[tata].push_back(i);
    }
    dfs(1);
    precalc();
    while(m--)
    {
        int u, v;
        in >> u >> v;
        out << lca(u, v) << "\n";
    }

    return 0;
}