Cod sursa(job #1984085)

Utilizator borcanirobertBorcani Robert borcanirobert Data 23 mai 2017 17:24:21
Problema Lowest Common Ancestor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 1.8 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;

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

const int MAXN = 100005;
const int MAXLOG = 19;
int N, M;
int t[MAXN];
int lv[MAXN];
int P[MAXN][MAXLOG];
int L[MAXN];

void Read();
void Precalculate();
void AnswerQuery( int x, int y );
int Level( int node );

int main()
{
	Read();
	Precalculate();
	
	int x, y;
	while ( M-- )
	{
		fin >> x >> y;
		AnswerQuery(x, y);
	}
	
	fin.close();
	fout.close();
	return 0;
}

void Read()
{	// citesc sirul tatilor
	fin >> N >> M;
	for ( int i = 2; i <= N; ++i )
		fin >> t[i];
}

void Precalculate()
{
	int i, j;
	
	memset(P, -1, sizeof(P));
	
	// P[i][0] este stramosul direct (tatal) lui i defapt
	for ( i = 2; i <= N; ++i )
		P[i][0] = t[i];
		
	// restul se calculeaza cu ajutorul relatiei de recurenta
	for ( j = 1; (1 << j) < N; ++j )
		for ( i = 1; i <= N; ++i )
			if ( P[i][j - 1] != -1 )
				P[i][j] = P[P[i][j - 1]][j - 1];
}

void AnswerQuery( int x, int y )
{
	// nodul y trebuie sa fie cel mai indepartat de radacina
	if ( Level(x) > Level(y) )
		swap(x, y);
	
	// caut log in baza 2 din nivelul la care se afla nodul
	// cel mai indepartat de radacina, adica nodul y
	int log;
	for ( log = 1; (1 << log) <= Level(y); ++log );
	--log;
	
	// aduc nodurile la acelasi nivel
	for ( int i = log; i >= 0; --i )
		if ( Level(P[y][i]) >= Level(x) )
			y = P[y][i];
	
	if ( x == y )
	{
		fout << x << '\n';
		return;
	}
	
	// caut stramosul lor comun
	for ( int i = log; i >= 0; --i )
		if ( P[y][i] != -1 && P[y][i] != P[x][i] )
			x = P[y][i], y = P[x][i];
	
	fout << t[x] << '\n';
}

int Level( int node )	// determin la ce nivel se afla nodul node
{
	if ( node == -1 )
		return -1;
	if ( node == 1 )
		return 1;
	int& a = L[node];
	
	if ( a == 0 )
		return a = 1 + Level(t[node]);
	return a;
}