Cod sursa(job #2803407)

Utilizator dana24hdDana N dana24hd Data 19 noiembrie 2021 23:11:55
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.62 kb
#include <iostream>
#include <fstream>
#include <bits/stdc++.h>

using namespace std;

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

const int NMAX=300000;
const int LGMAX=20;

/// adia[i] = lista de vecini ai lui i
vector <int> adia[NMAX];

int h[NMAX];
//int val_hash[NMAX];
//int sp[NMAX];
//int val_nod[NMAX];
/// suma hash 1,2..N
//int target_sum;

//mt19937 rnd(time(0));

/// stramos[p][i]= al 2^p -lea stramos al lui i
/// stramos [0][i]=tatal lui i
/// stramos [2][i] = tatal tatalui tatalui tatalui lui i

/// stramos[p][i]=stramos[p-1][ stramos[p-1][i] ]

int stramos[LGMAX][NMAX];


void Dfs(int nod, int t){

    //sp[nod]=sp[tata]+val_hash[val_nod[nod]];
    stramos[0][nod]=t;
    for(int i=1; i<=LGMAX; i++)
        stramos[i][nod]=stramos[i-1][stramos[i-1][nod]];
    h[nod]=1+h[t];
    //cout<<"Am ajuns in nodul "<<nod<<" din "<<t<<'\n';
    for( auto i: adia[nod] ){
        if( i!=t )
            Dfs(i, nod);
    }

}

/*ridica un nod cu x noduri mai sus in arbore*/
void Up( int &nod, int x )
{

        for(int b=0; b<LGMAX; b++){
            if( x&(1<<b) )
                nod=stramos[b][nod];
        }

}

/*returneaza cel mai jos stramos comun a 2 noduri diferite*/
int Lca(int a, int b){

    if( h[a]<h[b] )
        swap(a, b);

    Up(a, h[a]-h[b]);
    //out<<"alo";

    /// daca initial unul e un stramos al celuilalt
    if( a==b ){
        //cout<<" stramos al celuilalt ";
        return a;
    }


    /// ne mutam in sus cat timp nu dam de un stramos comun
    for(int i=LGMAX-1; i>=0; i--){
        if(stramos[i][a]!=stramos[i][b])
            a=stramos[i][a], b=stramos[i][b];
    }

    return stramos[0][a]; /// fiul

}

/// arbore cu sume partiale sp
/// a si b stramos
/// s[a]+...+s[b] = sp[a] - sp[ tata[b] ]
/// b nu este neaparat stramos:
/// sp[a]+sp[b]-sp[LCA]-sp[tatal LCA]

/*
void Check(int a, int b){

    int lca=Lca(a, b);
    int sum_lant=sp[a]+sp[b]-sp[lca]-sp[stramos[0][lca]];

    return sum_lant==target_sum;

} */

int main()
{

    int n, m;
    in>>n>>m;

    /**
    for(int i=0; i<NMAX; i++){
        val_hash[i]=rnd();
    }

    for(int i=1; i<=M; i++){
        target_sum+=val_hash[i];
    } **/

    for(int i=1; i<=n-1; i++){
        int a;
        in>>a;
        stramos[0][i+1]=a;
        //Dfs( i+1, a );
        //adia[a].push_back(a+1);
        //adia[a+1].push_back(a);
    }

    for(int i=1; i<=n-1; i++){
        Dfs( i+1, stramos[0][i+1] );
    }

    int x, y;
    for(int i=1; i<=m; i++){
        in>>x>>y;
        out<<Lca( x, y )<<'\n';
    }

    return 0;
}