/*
* 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 ] ;
ifstream f ( "lca.in" ) ;
ofstream g ( "lca.out" ) ;
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 , lca , father , cnt = 0 ;
f >> n >> q ;
for ( i = 2 ; i <= n ; ++ i )
{
f >> 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 -- )
{
f >> x >> y ;
g << LCAsol4.query_lca_sol4( x , y , firstap , rmq_euler , lg , level ) << "\n" ;
}
return 0 ;
}