Cod sursa(job #3276271)

Utilizator and_Turcu Andrei and_ Data 13 februarie 2025 02:11:47
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.15 kb

#include <bits/stdc++.h>
 /// 1:28

using namespace std;

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

const int N = 100007,EXP_MAX=18;
int n,q;
vector<int> a[N];
int adancime[N];
int ultima_aparitie_tur[N];
int rmq_table[19][N*2],p2[19];
vector<int>tur_eulerian;
int index_tur;


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


void Update_Tur(int x)
{
    tur_eulerian.push_back(x);
    ultima_aparitie_tur[x]=index_tur;
    index_tur++;
}

void Generare_Tur_Eulerian(int x,int tata)
{
    Update_Tur(x);
    for(auto y:a[x])
        if( y!=tata )
        {
            Generare_Tur_Eulerian(y,x);
            Update_Tur(x);
        }
    }
    
    void Generare_RMQ()
    {
        p2[0]=1;
        for(int i=1;i<=EXP_MAX;i++)
        p2[i]=p2[i-1]*2;
        
        for(int i=0;i<index_tur;i++)
        rmq_table[0][i]=tur_eulerian[i];
        for(int e=1;e<=EXP_MAX;e++)
        {
        int p_aux = 1 << e;
        for(int i=0;i-1+p_aux<index_tur;i++)
        {
            rmq_table[e][i]=rmq_table[e-1][i];
            if(  adancime[ rmq_table[e-1][i+p_aux/2] ] <adancime[ rmq_table[e][i] ] )
            rmq_table[e][i] = rmq_table[e-1][i+p_aux/2];
        }   
    }
}

void Generare_Adancime_noduri(int x,int tata,int nivel)
{
    adancime[x]=nivel;
// cout << x << " : " << nivel << "\n";
    for(auto y:a[x])
        if( y!=tata )
            Generare_Adancime_noduri(y,x,nivel+1);
}

void Generare()
{
    Generare_Adancime_noduri(1,0,1);
    
    Generare_Tur_Eulerian(1,0);
    
    Generare_RMQ();
}

int Lca(int x,int y)
{
    int ux = ultima_aparitie_tur[x];
    int uy = ultima_aparitie_tur[y];
    if( ux>uy )
        swap(ux,uy);
    int e=0;
    while( (1<<e) <= uy-ux+1 )
        e++;
    e = max(0,e-2);

    int z = rmq_table[ e ][ ux ];
    if( adancime[ rmq_table[ e ][ ux+(1<<e) ] ] < adancime[ z ] ) 
        z = rmq_table[ e ][ ux+(1<<e) ];
    return z;
    return 0;
}

int main()
{
    Citire();
    Generare();
    for(int i=1;i<=q;i++)
    {
        int x,y;
        fin >> x >> y;
        fout << Lca(x,y) << "\n";
    }
    return 0;
}