Cod sursa(job #2324440)

Utilizator Andrei-27Arhire Andrei Andrei-27 Data 20 ianuarie 2019 18:50:08
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 8.93 kb
/*
 * Code by Arhire Andrei
 * Colegiul National " Spiru Haret " Tecuci
*/

#include <bits/stdc++.h>
#define pb push_back
using namespace std ;

const int NMAX = ( 1 << 10 ) ;
const int SQRTNMAX = ( 1 << 5 )  ;
const int LOGNMAX = 20 ;

vector < int > v [ NMAX ] ;

class RangeMinimumQuery
{
public :

    int rmq_brutforce_sol1 ( int x , int y , int A [ NMAX ] )
    {
        int i , minim ;
        minim = A [ x ] ;
        for ( i = x + 1 ; i <= y ; ++ i )
        if ( A [ i ] < minim )  minim = A [ i ] ;
        return minim ;
    }
     void rmq_sol2 ( int rmq [ NMAX ][ NMAX ] , int A [ NMAX ] , int n )
    {
        int i , j ;
        for ( i = 1 ; i <= n ; ++ i )
        rmq [ i ][ i ] = A  [ i ] ;
        for (  i = 1 ; i < n ; ++ i )
        for ( j = i + 1; j <= n ; ++ j )
        rmq [ i ][ j ] = min ( rmq [ i ][ j - 1 ] , A [ j ] ) ;
    }

    int query_sol2 ( int rmq [ NMAX ][ NMAX ] , int a , int b  )
    {
        if ( a > b )    swap ( a , b ) ;
        return rmq [ a ][ b ] ;
    }

    void rmq_sol3 ( int rmq [ SQRTNMAX ] , int A [ NMAX ] , int n , int k )
    {
       int i , cnt = 0 ;
       for( i = 1 ; i <= n ; ++ i )
       {
            if ( !( ( i - 1 ) %  k  ) )
                rmq [ ++ cnt ] = A [ i ] ;
            else
                rmq [ cnt ] = min ( rmq [ cnt ] , A [ i ] ) ;
       }
    }

    int query_sol3 ( int rmq [ SQRTNMAX ] , int A [ NMAX ] , int n , int k , int st , int dr )
    {
        int i , minim = ( 1 << 30 ) , t ;
        for ( i = st ; ( i - 1 ) % k && i <= dr ; ++ i )   minim = min ( minim , A [ i ] ) ;

        t = i / k + 1 ;
        for ( ; i + k - 1 <= dr ; i += k  )   minim = min ( minim , rmq [ t ++ ] ) ;

        for ( ; i <= dr ; ++ i )        minim = min ( minim , A [ i ] ) ;

        return minim ;
    }

    void rmq_sol4 ( int rmq [ LOGNMAX ][ NMAX ] , int lg [ NMAX ] , int A [ NMAX ] , int n )
    {
        int i ,j ;
        for ( i = 1 ; i <= n ; ++ i )    rmq [ 0 ][ i ] = A [ i ] ;

        for ( i = 1 ; ( 1 << i ) <=  n ; ++ i )
        for ( j = 1 ; j + ( 1 << i ) <= n + 1 ; ++ j )
        rmq [ i ][ j ] = min ( rmq [ i - 1 ][ j ] , rmq [ i - 1 ][ j + ( 1 << ( i - 1 ) ) ] ) ;

        for ( i = 2 ; i <= n ; ++ i )   lg [ i ] = lg [ i >> 1 ] + 1 ;

    }

    int query_sol4 ( int rmq [ LOGNMAX ][ NMAX ] , int lg [ NMAX ] , int a , int b )
    {
        if ( a > b )    swap ( a , b ) ;
        int log = lg [ b - a + 1 ] ;
        return  min ( rmq [ log ][ a ] , rmq [ log ][ b - ( 1 << log ) + 1 ] ) ;
    }

      void rmq__father ( int rmq_father[ LOGNMAX ][ NMAX ] , int Father [ NMAX ] , int n )
    {
        int i , j ;
        for (  i = 1 ; i <= n ; ++ i )    rmq_father [ 0 ][ i ] = Father [ i ] ;

        for (  i = 1 ; ( 1 << i ) <= n ; ++ i )
        for (  j = 1 ; j <= n ; ++ j )   rmq_father [ i ][ j ] = rmq_father [ i - 1 ][ rmq_father [ i - 1 ][ j ] ] ;
    }

    int  query_rmq__father( int rmq_father [ LOGNMAX ][ NMAX ] , int nod , int nr , int log )
    {

        while ( log -- )
        if ( ( 1 << log ) & nr )
        nod = rmq_father [ log ][ nod ] ;

        return nod ;
    }
    void rmq__edge ( int rmq_father[ LOGNMAX ][ NMAX ], int rmq_edge [ LOGNMAX ][ NMAX ] , int Father [ NMAX ] , int Father_edge [ NMAX ] , int n )
    {
        int i , j ;
        for ( i = 1 ; i <= n ; ++ i )
        {
            rmq_father [ 0 ][ i ] = Father [ i ] ;
            rmq_edge [ 0 ][ i ] = Father_edge [ i ] ;
        }

        for ( i = 1 ; ( 1 << i ) <= n ; ++ i )
        for ( j = 1 ; j <= n ; ++ j )
        {
            rmq_father [ i ][ j ] = rmq_father [ i - 1 ][ rmq_father [ i - 1 ][ j ] ] ;
            rmq_edge [ i ][ j ] = min ( rmq_edge [ i - 1 ][ j ] , rmq_edge [ i - 1 ][ rmq_father [ i - 1 ][ j ] ] ) ;
        }
        }

    int query_rmq__edge (  int rmq_father[ LOGNMAX ][ NMAX ], int rmq_edge [ LOGNMAX ][ NMAX ]  , int nod , int nr , int log )
    {

            int min_edge = ( 1 << 30 ) ;
            while ( log --  )
            if ( ( ( 1 << log ) & nr )  )
            {
            min_edge = min ( rmq_edge [ log ][ nod ] , min_edge ) ;
            nod = rmq_father [ log ][ nod ] ;
            }
        return min_edge ;
    }

};

class LowestCommonAncestor
{
public :
    int lca_brutforce_sol1 ( int x , int y , int Father [ NMAX] , int level [ NMAX ] )
     {
        while ( x != y )
        {
        if ( level [ x ] > level [ y ] )
            x = Father [ x ] ;
        else
            y = Father [ y ] ;
        }
        return x ;
     }
     void dfs_sol2 ( int nod , int Father [ NMAX ] , int Level [ NMAX ] , int GR [ NMAX ] , int sqrtn )
    {
    Level [ nod ] = Level [ Father [ nod ] ] + 1 ;

    if ( Level [ nod ] < sqrtn )
        GR [ nod ] = 1 ;
    else
    {
        if ( ! ( Level [ nod ] % sqrtn ) )
            GR [ nod ] = Father [ nod ] ;
        else
            GR [ nod ] = GR [ Father [ nod ] ] ;
    }
    for( size_t i = 0 ; i < v [ nod ].size() ; ++ i )
        dfs_sol2 ( v [ nod ][ i ] , Father , Level , GR , sqrtn ) ;
    }

    int lca_sol2 ( int x , int y , int Father [ NMAX ] , int Level [ NMAX ] , int GR [ NMAX ] )
    {

    while ( GR [ x ] != GR [ y ] )
    {
        if ( Level [ x ] > Level [ y ] )
            x = GR [ x ] ;
        else
            y = GR [ y ] ;
    }

    while ( x != y )
    {
        if ( Level [ x ] > Level [ y ] )
            x = Father [ x ] ;
        else
            y = Father [ y ] ;
    }
    return x ;
    }

    void dfs_sol3 ( int nod , int father , int Level [ NMAX ] )
    {
        Level [ nod ] = Level [ father ] + 1 ;
        for ( size_t i = 0 ; i < v[  nod ].size() ; ++ i )
        {
            dfs_sol3 ( v [ nod ][ i ] , nod , Level ) ;
        }
    }

    int lca_query_sol3 ( int x , int y , int Level [ NMAX ] , int Father [ NMAX ] , int rmq_father [ LOGNMAX ][ NMAX ] )
    {
        int log , i ;
        if ( Level [ x ] > Level [ y ] )    swap ( x , y ) ;

        for ( log = 0 ; ( 1 << log ) <= Level [ y ] ; log ++ ) ;

        for (  i = log ; i >= 0 ; -- i )
        {
            if ( Level [ y ] - ( 1 << i ) >= Level [ x ] )
            y = rmq_father [ i ][ y ] ;
        }
        if ( x == y )   return x ;

        for (  i = log ; i >= 0 ; -- i )
        if ( rmq_father [ i ][ x ] != rmq_father [ i ][ y ] )
        {
            x = rmq_father [ i ][ x ] ;
            y = rmq_father [ i ][ y ] ;
        }
        return Father [ x ] ;
    }
    void dfs_sol4 ( int nod , int father , int & cnt , int euler  [ 2 * NMAX ] , int level [ NMAX ] , int firstap [ NMAX ] )
    {
        level [ nod ] = level [ father ] + 1 ;
        euler [ ++ cnt ] = nod ;
        firstap [ nod ] = cnt ;
        for ( size_t i = 0 ; i <  v[ nod ].size() ; ++ i )
        {
            dfs_sol4 ( v [ nod ][ i ] , nod , cnt , euler , level , firstap ) ;
            euler [ ++ cnt ] = nod ;
        }
    }

    void rmq_sol4 ( int cnt , int rmq_euler [ LOGNMAX ][ 2 * NMAX ] , int level [ NMAX ] , int euler [ 2 * NMAX ] , int lg [ 2 * NMAX ] )
    {
        int i , j ;
        for ( i = 2 ; i <= cnt ; ++ i )   lg [ i ] = lg [ i >> 1 ] + 1 ;

        for ( i = 1 ; i <= cnt ; ++ i )   rmq_euler [ 0 ][ i ] = euler [ i ] ;

        for( i = 1 ; ( 1 << i ) <= cnt ; ++ i )
        for( j = 1 ; j + ( 1 << i ) <= cnt + 1 ; ++ j )
        {
            if ( level [ rmq_euler [ i - 1 ][ j ] ] > level [ rmq_euler [ i - 1 ][ j + ( 1 << ( i - 1 ) ) ] ] )
                        rmq_euler [ i ][ j ] = rmq_euler [ i - 1 ][ j + ( 1 << ( i - 1 ) ) ] ;
            else        rmq_euler [ i ][ j ] = rmq_euler [ i - 1 ][ j ] ;
        }
    }

    int query_lca_sol4 ( int x , int y , int firstap [ NMAX ] , int rmq_euler [ LOGNMAX ][ 2 * NMAX ] , int lg [ 2 * NMAX ] , int level [ NMAX ] )
    {
        int i , st , dr ;
        st = firstap [ x ] ;
        dr = firstap [ y ] ;
        if ( st > dr )  swap ( st , dr ) ;

        i = lg [ dr - st + 1 ] ;

        if ( level [ rmq_euler [ i ][ st ] ] < level [ rmq_euler [ i ][ dr - ( 1 << i ) + 1 ] ] )
            {
                return rmq_euler [ i ][ st ]  ;
            }
            return rmq_euler [ i ][ dr - ( 1 << i ) + 1 ]  ;
    }

};

int main ()
{
    int  level [ NMAX ] = {0} , euler [ 2 * NMAX ] = {0} , lg [ 2 * NMAX ] = {0} ;
    int rmq_euler [ LOGNMAX ][ 2 * NMAX ] = {0} , firstap [ NMAX ] = {0} ;

    int n , q , i ,x , y , father , cnt = 0 ;
    cin >> n >> q ;
    for ( i = 2 ; i <= n ; ++ i )
    {
        cin >> father ;
        v [ father ] .pb ( i ) ;
    }
    LowestCommonAncestor LCAsol4 ;
    LCAsol4.dfs_sol4( 1 , 0 , cnt , euler , level , firstap ) ;
    LCAsol4.rmq_sol4( cnt , rmq_euler , level , euler , lg ) ;

    while ( q -- )
    {
        cin >> x >> y ;
        cout << LCAsol4.query_lca_sol4( x , y , firstap , rmq_euler , lg , level ) << "\n" ;
    }
    return 0 ;
}