Cod sursa(job #3226666)

Utilizator and_Turcu Andrei and_ Data 22 aprilie 2024 14:36:16
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.88 kb
#include <bits/stdc++.h>

using namespace std;


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

const int N=100007;
const int N_TUR=100007*2+1;
int n,q;
vector<int>g[N];
int ordine[N_TUR],nivel[N_TUR],poz_tur,aparitie_tur[N];
int tabel_RMQ[19][N_TUR],exponent2[N_TUR];

void Citire()
{
    fin >> n >> q;
    for(int i=2;i<=n;i++)
    {
        int tata;
        fin >> tata;
        g[tata].push_back(i);
    }
}

void Adaugare_ordine(int x,int adancime)
{
    ordine[++poz_tur]=x;
    nivel[poz_tur]=adancime;
    aparitie_tur[x]=poz_tur;
}

inline void Tur_eulerian(int x,int adancime)
{
    Adaugare_ordine(x,adancime);
    for(auto y:g[x])
    {
        Tur_eulerian(y,adancime+1);
        Adaugare_ordine(x,adancime);
    }
}

void Generare_RMQ()
{
    for(int i=2;i<=2*n-1;i++)    ///            / ///
        exponent2[i]=exponent2[i/2]+1;
    for(int i=1;i<=poz_tur;i++)
        tabel_RMQ[0][i]=i;
    for(int i=1;i<=exponent2[poz_tur];i++)
    {
        int putere=(1<<i);
        for(int j=1;j<=poz_tur-putere+1;j++)
        {
            if( nivel[ tabel_RMQ[i-1][j] ]<nivel[ tabel_RMQ[i-1][j+putere/2] ] )
                tabel_RMQ[i][j]=tabel_RMQ[i-1][j];
            else
                tabel_RMQ[i][j]=tabel_RMQ[i-1][j+putere/2];
        }
    }
}

int LCA(int x,int y)
{
    int st= min( aparitie_tur[x],aparitie_tur[y] );
    int dr= max( aparitie_tur[x],aparitie_tur[y] );
    int expxy = exponent2[ dr-st+1 ];
    int putere = 1<<expxy;
    if( nivel[ tabel_RMQ[expxy][st] ]<nivel[ tabel_RMQ[expxy][dr-putere+1] ] )
        return ordine[tabel_RMQ[expxy][st]];
    return ordine[tabel_RMQ[expxy][dr-putere+1]];
}

int main()
{
    Citire();
    Tur_eulerian(1,1);
    Generare_RMQ();
    for(int i=1;i<=q;i++)
    {
        int x,y;
        fin >> x >> y;
        fout << LCA(x,y) << "\n";
    }
    fin.close();fout.close();
    return 0;
}