Cod sursa(job #2343045)

Utilizator Andrei-27Arhire Andrei Andrei-27 Data 13 februarie 2019 17:21:36
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.19 kb
#include <bits/stdc++.h>
#define pb push_back
using namespace std ;
const int NR = 100002 ;
ifstream in ("lca.in") ;
ofstream out ("lca.out") ;

vector < int > v [ NR ] ;
int euler [ 2 * NR ] , firstap [ NR ] , cnt ,n , q , rmq [ 20 ] [ 2 * NR ] , lvl [ 2 * NR ] , lg [ 2 * NR ];
void dfs_euler ( int nod )
{
    euler [ ++ cnt ] = nod ;
    firstap [ nod ] = cnt ;
    for ( size_t i = 0 ; i < v [ nod ].size() ; ++ i )
    {
        lvl [ v [ nod ][ i ] ] = 1 + lvl [ nod ] ;
        //cout << nod << ' ' << v [ nod ][ i ] << '\n' ;
        dfs_euler ( v [ nod ][ i ] ) ;

        euler [ ++ cnt ] = nod ;
    }
}

void range ()
{

    int i , j ;
    for ( i = 2 ; i <= cnt ; ++ i ) lg [ i ] = lg [ i >> 1 ] + 1 ;
    for ( i = 1 ; i <= cnt ; ++ i ) rmq [ 0 ][ i ] = euler [ i ] ;

    for ( i = 1 ; ( 1 << i ) <= cnt ; ++ i )
    for ( j = 1 ; j + ( 1 << i ) <= cnt + 1 ; ++ j )
    {
        rmq [ i ][ j ] = rmq [ i - 1 ][ j ] ;
        if ( lvl [ rmq[ i - 1 ][ j + ( 1 << ( i - 1 ) ) ] ] < lvl [ rmq [ i - 1 ][ j ] ] )
        rmq [ i ] [ j ] = rmq [ i - 1 ][ j + ( 1 << ( i - 1 ) ) ] ;
    }
}

int query ( int x , int y )
{
    x = firstap [ x ] ;
    y = firstap [ y ] ;
    if ( x > y )    swap ( x , y ) ;
    int best , log = lg [ y - x + 1 ] ;
    best = rmq [ log ][ x ] ;
    if ( lvl [ rmq [ log ][ x ] ] > lvl [ rmq [ log ][ y - ( 1 << log ) + 1 ] ] )
    best = rmq [ log ][ y - ( 1 << log ) + 1 ] ;
    return best ;
}

int main ()
{
    int i , j ;
    in >> n >> q ;
    lvl [ 1 ] = 1 ;
    for ( int i = 2 ; i <= n ; ++ i )
    {
        int father ; in >> father ;
        v [ father ].pb ( i ) ;
    }
    dfs_euler( 1 ) ;
    range() ;
    //cout << query ( 5 , 6 ) ;

        for ( ; q-- ; )
        {
            int a , b ;
            in >> a >> b ;
            out << query ( a , b ) << '\n' ;
        }
    //for ( int i = 1 ; i <= cnt ; ++ i ) cout << euler [ i ] << ' ' ;
    //cout << '\n' ;
    //for ( int i = 1 ; i <= cnt ; ++ i ) cout << lvl [ euler [ i ] ] << ' ' ;
    //for ( i = 0 ; ( 1 << i ) <= cnt ; ++ i , cout << '\n' )
    //for ( j = 1 ; j + ( 1 << i ) <= cnt + 1 ; ++ j )    cout << rmq [ i ][ j ] << ' ' ;

}