Cod sursa(job #1840037)

Utilizator xtreme77Patrick Sava xtreme77 Data 3 ianuarie 2017 18:22:34
Problema Lowest Common Ancestor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.5 kb
#include <bits/stdc++.h>

using namespace std ;

#define FORN(a,b,c) for(int a=b;a<=c;++a)
#define FORNBACK(a,b,c) for (int a=b;a>=c;--a)
#define mp make_pair
#define pb push_back

const int MAX = 1e5 + 14 ;
const int LG = 7 ;

vector < int > gr [ MAX ], lant [ MAX ] ;
int nrlant ;
int lantdenod[MAX] ;
int poz [MAX] ;
int sub [MAX] ;
int tata [MAX] ;

int dp [LG] [MAX] ;

void dfs ( int nod )
{
	sub [nod] = 1 ;
	int where = 0 ;
	for ( auto x : gr [nod] ) {
		tata [x] = nod ;
		dfs (x);
		sub [nod] += sub [x] ;
		if (sub [x] > sub [where] ) {
			where = x ;
		}
	}
	if (gr[nod].size()==0){
		++ nrlant ;
		lant [nrlant].pb(nod) ;
		poz [nod] = lant [nrlant].size() - 1; 
		lantdenod [nod] = nrlant ;
	}
	else {
		lant [lantdenod[where]].pb(nod) ;
		poz [nod] = lant [lantdenod[where]].size() - 1 ;
		lantdenod [nod] = lantdenod[where] ;
	}
}

int sz ;
int lvl [MAX] ;
int lg [MAX] ;

void dfs2 ( int nod )
{
	//cout << nod << ' ' << poz [nod] << '\n';
	if ( poz [nod] == lant [lantdenod[nod]].size() - 1 ) {
		lvl [lantdenod[nod]] = sz ; 
		++ sz ;
	}
	for ( auto x : gr [nod] ) {
		dfs2(x) ;
	}

	if ( poz [nod] == lant [lantdenod[nod]].size() - 1 ) {
		-- sz ;
	}
}

int lca ( int x , int y )
{
	if ( lvl[lantdenod [x]] < lvl [lantdenod[y]] ) {
		swap (x,y) ;
	}
	int dif = lvl[lantdenod [x]] - lvl [lantdenod[y]] ;
	for ( int put = lg [dif] + 1 ; put >= 0 ; -- put ) {
		if ( dif & ( 1 << put ) ) {
			x = dp [put][x] ;
		}
	}
	if ( lantdenod [x] == lantdenod [y] ){
		if (poz[x] > poz [y]) {
			return x ; 
		}
		return y ;
	}
	for ( int put = lg [lvl[lantdenod[x]]] + 1 ; put >= 0 ; -- put ){
		if ( dp [put][x] and dp [put][y] and lant[dp [put] [x]] != lant[dp [put] [y]] ) {
			x = dp [put] [x] ;
			y = dp [put] [y] ;
		}
	}
	if ( lantdenod [x] == lantdenod [y] ){
		if (poz[x] > poz [y]) {
			return x ; 
		}
		return y ;
	}
	if ( poz [dp[0][x]] > poz [dp[0][y]] )  {
		return dp[0][x] ;
	}
	return dp [0][y] ;
}

int main ()
{
	freopen ("lca.in", "r", stdin) ;
	freopen ("lca.out" ,"w", stdout) ;
	int n, m;
	cin >> n >> m ;
	FORN ( i , 2 , n ) {
		int x ;
		cin >> x ;
		gr [x].pb (i) ;
		lg [i] = lg [i >> 1] + 1 ;
	}
	dfs (1) ;
	dfs2 (1) ;
	FORN ( i , 1 , n ) {
		dp [0] [i] = tata [ lant [ lantdenod [i] ].back() ] ;
	}
	for ( int j = 1 ; j <= lg [sz] + 1 ; ++ j ) {
		for ( int i = 1 ; i <= n ; ++ i ) {
			dp [j] [i] = dp [j-1] [dp[j-1][i]] ;
		}
	}
	/*cout << dp[0][8] << ' ' << dp[0][9] << '\n' ;
	cout << dp [1] [9] << '\n';
	return 0 ;*/
	while (m--) 
	{
		int x,y ;
		cin >> x >> y ;
		cout << lca (x,y) << '\n' ;
	}
	return 0 ;
}