Cod sursa(job #731025)

Utilizator radu_voroneanuVoroneanu Radu Stefan radu_voroneanu Data 7 aprilie 2012 12:31:09
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.73 kb
//Voroneanu Radu
//LCA - folosind rmq pe grupe de lungimi (log N / 2)
//Complexitate : O(N+M)
//Memorie : O(N)
//Timp de lucru : 60 min

#include <stdio.h>
#include <vector>
#include <algorithm>
#include <string.h>

using namespace std;

#define MAXN 100002
#define MAXLOG 16
#define MAXG 12

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<<MAXG)][MAXG][MAXG];
int RMQ[MAXLOG][2*MAXN/MAXG + 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/MAXG] |= (1<<(E%MAXG));
	}
}

inline void precalcul()
{
	int mask, i, j, minim;
	int Nr[MAXG];
	
	memset(Nr, 0, sizeof(Nr));
	
	for (mask = 0; mask < (1<<MAXG); ++mask)
		for (i = 0; i < MAXG; ++i){
			Nr[i] = 0; minim = i;
			P[mask][i][i] = i;
			for (j = i+1; j < MAXG; ++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 / MAXG) + 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][MAXG-1] + i * MAXG];
	
	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 / MAXG == y / MAXG){
		Ans = Q[ P[Grup[x/MAXG]][x%MAXG][y%MAXG] + (x/MAXG)*MAXG];
		return;
	}
	
	int grupx, grupy;
	grupx = x / MAXG;
	grupy = y / MAXG;
	
	if (Lv[Ans] > Lv[ Q[ P[Grup[grupx]][x%MAXG][MAXG-1] + grupx * MAXG ] ] )
		Ans = Q[ P[Grup[grupx]][x%MAXG][MAXG-1] + grupx * MAXG ];
	if (Lv[Ans] > Lv[ Q[ P[Grup[grupy]][0][y%MAXG] + grupy * MAXG ] ] )
		Ans = Q[ P[Grup[grupy]][0][y%MAXG] + grupy * MAXG ];
	
	
	x = x / MAXG + 1;
	y = y / MAXG - 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;
}