Pagini recente » Cod sursa (job #1659655) | Cod sursa (job #1210601) | Cod sursa (job #2619205) | Cod sursa (job #1416009) | Cod sursa (job #2263382)
#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 ) << '\n' ;
}
return 0;
}