Cod sursa(job #731024)

Utilizator radu_voroneanuVoroneanu Radu Stefan radu_voroneanu Data 7 aprilie 2012 12:26:45
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.5 kb
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <string.h>

using namespace std;

#define MAXN 100002
#define MAXLOG 16

int Lv[MAXN], T[MAXN], First[MAXN], Grup[MAXN], lg[MAXN];
int Q[MAXN*2];
vector<int> G[MAXN];
int N, M, E;
int i, x, y;
int Ans;
int P[(1<<8)][8][8];
int RMQ[MAXLOG][MAXN/4 + 2];

void df(int nod)
{
	vector<int>::iterator it;
	
	Lv[nod] = Lv[T[nod]] + 1;
	
	Q[++E] = nod;
	First[nod] = E;
	for (it = G[nod].begin(); it != G[nod].end(); ++it){
		df(*it);
		Q[++E] = nod;
		Grup[E>>3] |= (1<<(E&7));
	}
}

inline void precalcul()
{
	int mask, i, j, minim;
	int Nr[8];
	
	memset(Nr, 0, sizeof(Nr));
	
	for (mask = 0; mask < (1<<8); ++mask)
		for (i = 0; i < 8; ++i){
			Nr[i] = 0; minim = i;
			P[mask][i][i] = i;
			for (j = i+1; j < 8; ++j){
				if (mask & (1<<j)) 
					Nr[j] = Nr[j-1] - 1;
				else 
					Nr[j] = Nr[j-1] + 1;
				if (Nr[minim] > Nr[j])
					minim = j;
				P[mask][i][j] = minim;
			}
		}
}

inline void rmq_grupe()
{
	int i, j, l, W;
	
	W = (E >> 3) + 1;
	
	lg[1] = 0;
	for (i = 2; i < W; ++i)
		lg[i] = lg[i>>1] + 1;
	
	for (i = 0; i < W; ++i)
		RMQ[0][i] = Q[P[Grup[i]][0][7] + (i<<3)];
	
	for (i = 1; (1<<i) <= W; ++i)
		for (j = 0; j < W - (1<<i) + 1; ++j)
		{
			l = 1<<(i-1);
			RMQ[i][j] = RMQ[i-1][j];
			if (Lv[ RMQ[i][j] ] > Lv[ RMQ[i-1][j+l] ])
				RMQ[i][j] = RMQ[i-1][j+l];
		}
}

inline void rmq(int x, int y)
{
	int diff, l, sh;
	
	if (x > y)
		swap(x,y);
	
	if ( (x >> 3) == (y >> 3) ){
		Ans = Q[ P[Grup[x>>3]][x&7][y&7] + ((x>>3)<<3 )];
		return;
	}
	
	int grupx, grupy;
	grupx = x >> 3;
	grupy = y >> 3;
	
	if (Lv[Ans] > Lv[ Q[ P[Grup[grupx]][x&7][7] + (grupx << 3) ] ] )
		Ans = Q[ P[Grup[grupx]][x&7][7] + (grupx << 3) ];
	if (Lv[Ans] > Lv[ Q[ P[Grup[grupy]][0][y&7] + (grupy <<3) ] ] )
		Ans = Q[ P[Grup[grupy]][0][y&7] + (grupy<<3) ];
	
	
	x = (x >> 3) + 1;
	y = (y >> 3) - 1;
	if (x <= y){
		diff = y - x + 1;
		l = lg[diff];
		sh = diff - (1<<l);
		if (Lv[Ans] > Lv[ RMQ[l][x] ])
			Ans = RMQ[l][x];
		if (Lv[Ans] > Lv[ RMQ[l][x + sh] ])
			Ans = RMQ[l][x + sh];
	}
}

int main()
{
	freopen("lca.in","r",stdin);
	freopen("lca.out","w",stdout);
	
	scanf("%d %d",&N,&M);
	for (i = 2; i <= N; ++i){
		scanf("%d",&T[i]);
		G[T[i]].push_back(i);
	}

	E = -1;
	df(1);
	
	precalcul();
	
	rmq_grupe();

	for (i = 1; i <= M; ++i){
		scanf("%d %d",&x,&y);
		
		Ans = x;
		
		rmq(First[x], First[y]);
		
		printf("%d\n",Ans);
	}
	return 0;
}