Cod sursa(job #404087)

Utilizator ErgoVicol Sergiu Constantin Ergo Data 25 februarie 2010 19:47:54
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.87 kb
#include <fstream>
#include <vector>

#define NMAX 100100
#define LGMAX 20

using namespace std;

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

int N, M, Min[5+LGMAX][LGMAX*NMAX], Pos[NMAX], EU[LGMAX*NMAX], LG[LGMAX*NMAX], Depth[LGMAX*NMAX], EULen, PMin[5+LGMAX][LGMAX*NMAX];
vector<int> C[NMAX];


void Citire(void)
{
	int i, x;
	
	fin >>N >>M;
	
	for (i = 2; i <= N; i++)
	{
		fin >>x;
		C[x].push_back(i);
	}
}

void DFS(int Nod, int Nivel)
{
	EU[++EULen] = Nod;
	Depth[EULen] = Nivel;
	Pos[Nod] = EULen;
	
	for (int i = 0; i < C[Nod].size(); i++)
	{
		DFS(C[Nod][i], Nivel+1);
		EU[++EULen] = Nod;
		Depth[EULen] = Nivel;
	}
}

void CalcLG(void)
{
	int i;
	
	for (i = 2; i <= EULen; i++)
		LG[i] = LG[i/2] + 1;
}

int minim(int a, int b)
{
	if (a < b) return a;
	else return b;
}

void GenereazaMin(void)
{
	int i, j;
	
	for (i = 1; i <= EULen; i++)
		Min[0][i] = Depth[i], PMin[0][i] = EU[i];
	
	for (j = 1; j <= LG[EULen]; j++)
		for (i = 1; i <= EULen; i++)
			Min[j][i] = NMAX;
	
	for (j = 1; j <= LG[EULen]; j++)
		for (i = 1; i <= EULen - (1 << j) + 1; i++)
		{
			if (Min[j-1][i] < Min[j-1][i + (1 << (j - 1))])
			{
				Min[j][i] = Min[j-1][i];
				PMin[j][i] = PMin[j-1][i];
			}
			else
			{
				Min[j][i] = Min[j-1][i + (1 << (j - 1))];
				PMin[j][i] = PMin[j-1][i + (1 << (j - 1))];
			}
		}
}

void AfiseazaRezultate(void)
{
	int i, a, b;
	
	for (i = 1; i <= M; i++)
	{
		fin >>a >>b;
		
		a = Pos[a];
		b = Pos[b];
		
		if (a > b) swap(a,b);
		
		if (Min[LG[b-a+1]][a] < Min[LG[b-a+1]][b + 1 - (1 << LG[b-a+1])])
			fout << PMin[LG[b-a+1]][a];
		else
			fout << PMin[LG[b-a+1]][b + 1 - (1 << LG[b-a+1])];
	
		fout <<'\n';
	}
	
	fin.close();
	fout.close();
}

int main()
{
	Citire();

	DFS(1,0);
	
	CalcLG();
	
	GenereazaMin();
	
	AfiseazaRezultate();
	
	return 0;
}