Cod sursa(job #1488508)

Utilizator valentin50517Vozian Valentin valentin50517 Data 19 septembrie 2015 09:36:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.58 kb
#include <fstream>
#include <iostream>
#include <cmath>

using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");

typedef struct nod{
	int key;
	nod *next;
} *lnod;

lnod A[100010];
int Euler[200010][18],N,M,Stack[100010],eul,st,Nivel[100010],niv,Index[100010];

void add(lnod &a,int key){
	lnod b = new nod;
	b->key = key;
	b->next = a;
	a = b;
}

void rez(int v){
	int w;
	while(A[v] != NULL){
		Stack[++st] = v;
		Euler[++eul][0] = v;
		if(Index[v] == 0) Index[v] = eul;
		Nivel[v] = niv++;
		w = A[v]->key;
		A[v] = A[v]->next;
		v = w;
	}
	
	Euler[++eul][0] = v;
	if(!Index[v]) Index[v] = eul;
	Nivel[v] = niv--;
}

void euler(){
	int v = 1;
	do{
		rez(v);
		v = Stack[st--];
	}while(st >= 0);	
}

int log2s(int n){
	return trunc(log2(n));
}

void RMQ_init(){
	for(int k = 1; k <= log2s(eul);k++){
		for(int i = 1; i +(1 << k) <= eul;i++){
			if(Nivel[Euler[i][k-1]] < Nivel[Euler[i + (1 << (k-1))][k-1]])
				Euler[i][k] = Euler[i][k-1];
			else
				Euler[i][k] = Euler[i + (1 << (k-1))][k-1];
		}
	}
}

int querry(int l, int r){
	int dif = log2s(r - l + 1);
	if(Nivel[Euler[l][dif]] < Nivel[Euler[r - (1 << dif)+1][dif]])
		return Euler[l][dif];
	else
		return Euler[r - (1 << dif) + 1][dif];
} 

int main(){
	int x,y;
	fin >> N >> M;
	for(int i = 2;i<=N;i++){
		fin >> x;
		add(A[x],i);
	}
	
	euler();
	RMQ_init();
	
	for(int i = 0;i<M;i++){
		fin >> x >> y;
		if(Index[x] > Index[y])
			fout << querry(Index[y],Index[x]);
		else
			fout << querry(Index[x],Index[y]);
		fout << '\n';
	}
		
	return 0;
}