Cod sursa(job #2955133)

Utilizator and_Turcu Andrei and_ Data 16 decembrie 2022 13:35:45
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.48 kb
#include <bits/stdc++.h>
#define N 100007
using namespace std;

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

int n,q,ct,ntur,nrmq;
vector<int> a[N];
vector<int> ultima(N,0);
vector<int> ordine(2*N,0);
vector<int> adancime(2*N,0);
int tabel[20][2*N+1];
int tabel_poz[20][2*N+1];


void parcurs_in_tur(int x,int nivel)
{
    ultima[x]=++ct;
    ordine[ct]=x;
    adancime[ct]=nivel;
}



void tur_eulerian(int x,int nivel)
{
    parcurs_in_tur(x,nivel);

    for( auto y:a[x] )
    {
        tur_eulerian(y,nivel+1);
        parcurs_in_tur(x,nivel);
    }
}

void RMQ()
{
    for(; (1<<nrmq)<=ntur ;nrmq++);
    if( !(1<<nrmq)!=ntur )nrmq--;
    for(int i=0;i<=nrmq;i++)
        tabel[i][0]= (1<<i);
    for(int i=1;i<=ntur;i++)
    {
        tabel[0][i]= ordine[i];
        tabel_poz[0][i]= i;
    }
    for(int i=1;i<=nrmq;i++)
        for(int j=1;j<=ntur-a[i][0]+1;j++)
            if( tabel[i-1][j] < tabel[i-1][ tabel[i-1][0]+j ]   )
            {
                tabel[i][j]=tabel[i-1][j];
                tabel_poz[i][j]=tabel_poz[i-1][j];
            }
            else
            {
                tabel[i][j]=tabel[i-1][ tabel[i-1][0]+j ];
                tabel_poz[i][j]=tabel_poz[i-1][ tabel[i-1][0]+j ];
            }
//    for(int i=0;i<=nrmq;i++)
//    {
//        cout << tabel[i][0] << "   " ;
//        for(int j=1;j<=ntur;j++)
//            cout << tabel_poz[i][j] << " ";
//        cout << "\n";
//    }
}


int log_2(int x)
{
    int st=0,dr=nrmq,mij;
    int raspuns=-1;
    while( st<=dr )
    {
        mij=( st+dr )/2;
        if( tabel[mij][0]>x )
            dr=mij-1;
        else
        {
            raspuns=tabel[mij][0];
            st=mij+1;
        }
    }
    return raspuns;

}
void Ans(int x,int y)
{
    int st=min( ultima[x],ultima[y] )    ;
    int dr=max( ultima[x],ultima[y] )    ;
    int dist=log2(dr-st+1);
    if( tabel[dist][st] < tabel[dist][dr-dist+1] )
        fout << ordine[ tabel_poz[dist][st] ] << "\n";
    else
        fout << ordine[ tabel_poz[dist][dr-dist+1] ] << "\n";
///
}

void Citire_t()
{
    fin >> n >> q;
    for(int i=2;i<=n;i++)
    {
        int x;
        fin >> x;
        a[x].push_back(i);
    }
    tur_eulerian(1,0);
    ntur=n*2-1;
    RMQ();
//    for(int i=1;i<=2*n-1;i++)cout << ordine[i] <<" ";
//    cout << "\n";
//    for(int i=1;i<=2*n-1;i++)cout << adancime[i] <<" ";

    for(int i=1;i<=q;i++)
    {
        int x,y;
        fin >> x >> y;
        Ans(x,y);
    }
    fin.close();
    fout.close();
}

int main()
{
    Citire_t();
    return 0;
}