Cod sursa(job #2263373)

Utilizator CodrutLemeniCodrut Lemeni CodrutLemeni Data 18 octombrie 2018 17:22:56
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.61 kb
#include <bits/stdc++.h>

using namespace std;

const long long N = 200010 ;
const long long LOGN = 20 ;
const long long INF = 2000000000 ;

vector < pair < long long , long long > > fullGraph [ N ] ;
vector < pair < long long , long long > > crTree [ N ] ;
vector < pair < long long , pair< long long , long long > > > delMuc ;
long long noNodes , noMuc ;

long long meetOrd [ N ] , firstMeet [ 2 * N ] , height [ N ] ;
long long nodeIdx , lcaNodes;

bool viz [ N ] ;
long long dist [ N ] ;
long long dijDist [ 40 ][ 2 ][ N ];

long long rmq [ N ] [ LOGN ];
long long lg [ N ];

void PargTree ( long long crNode , long long crHeight ){

    meetOrd [ ++lcaNodes ] = crNode ;
    firstMeet [ crNode ] = lcaNodes ;
    height [ lcaNodes ] = crHeight ;


    viz [ crNode ] = 1 ;


    for ( pair < long long , long long > crVec : crTree [ crNode ] ){

        if ( viz [ crVec.first ] ){
            continue ;
        }

        viz [ crVec.first ] = 1 ;

        PargTree( crVec.first , crHeight + 1 );

        height [ ++lcaNodes ] = crHeight ;
        meetOrd [ lcaNodes  ] = crNode ;
    }

}

long long minRmq ( long long a , long long b ){

    if ( height [ a ] < height [ b ] ){
        return a ;
    }
    return b ;
}


void generateRMQ (){

    for( long long i = 2 ; i <= lcaNodes ; i++){
        lg[i]=lg[i/2]+1;
    }

    for ( long long i = 1 ; i <= lcaNodes ; i++ ){
        rmq [ i ][ 0 ] = i ;
    }

    long long j , pow2 ;
    for ( j = 1 ,pow2=1 ; (pow2 <<1 ) <= lcaNodes ; pow2 <<= 1 , j++){
        for( long long i = 1 ; i + pow2 <= lcaNodes ; i++){
            rmq[ i ][ j ] = minRmq( rmq[ i ][ j - 1 ] , rmq[ i + pow2 ][ j - 1 ] );
        }
    }


}

long long getLca( long long x , long long y ){

    if ( firstMeet [ x ] > firstMeet [ y ] ){
        swap( x , y );
    }

    x = firstMeet [ x ];
    y = firstMeet [ y ];

    long long vlg = lg [ y - x + 1 ] ;

    return meetOrd [ minRmq( rmq [ x ][ vlg ] , rmq [ y - ( 1<<vlg ) + 1 ][ vlg ] ) ];
}



void CreateTree ( long long crNode , long long parent  ){

    viz [ crNode ] = 1 ;

    for ( pair < long long , long long > crVec : fullGraph [ crNode ] ){

        if ( viz [ crVec.first ] ){
            if ( crVec.first != parent ){
                delMuc.push_back( make_pair( crNode , crVec ));
            }

            continue ;
        }

        dist [ crVec.first ] = dist [ crNode ] + crVec.second ;


        crTree[ crNode ].push_back( crVec );

        CreateTree( crVec.first , crNode );
    }

}


int main()
{

//    freopen("lca.in","r",stdin);
//    freopen("lca.out","w",stdout)
    freopen("file.in","r",stdin);
    freopen("file.out","w",stdout);

    cin >> noNodes ;

    long long noQuery ;
    cin >> noQuery ;

    noMuc = noNodes - 1 ;

    for ( long long i = 2 ; i <= noNodes ; i ++ ){
        long long x , y  , cost ;
        cin >> x ;
        y = i ;
        cost = 0 ;

        fullGraph [ x ].push_back( make_pair( y , cost ) );
        fullGraph [ y ].push_back( make_pair( x , cost ) );
    }

    CreateTree( 1 , 0 );
    memset ( viz , 0 , sizeof viz );
    PargTree( 1 , 0 );
    generateRMQ();

//    long long delIdx = 0 ;
//    for ( pair< long long , pair< long long , long long > > crMuc : delMuc ){
//        calcDist( crMuc.first , dijDist [ delIdx ][ 0 ] );
//        calcDist( crMuc.second.first , dijDist[ delIdx ][ 1 ] );
//
//        delIdx ++;
//    }

    while ( noQuery -- ){
        long long x , y ;
        cin >> x >> y;
        cout << getLca( x  ,  y ) ;
    }

    return 0;
}