Cod sursa(job #721397)

Utilizator psycho21rAbabab psycho21r Data 23 martie 2012 17:53:52
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.86 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <utility>
#define euler first
#define level second
using namespace std;
vector <int> tree[100001];
vector <pair <int, int> > eulerTree;
vector <int> log2;
int RMQ[100000][18], position[100001];
int minRMQ(int A, int B)
{
	if(eulerTree[A].level < eulerTree[B].level)
		return A;
	return B;
}
void getEulerAndLevels(int node, int nodeLevel)
{
	position[node] = eulerTree.size();
	eulerTree.push_back(make_pair(node, nodeLevel));
	if(tree[node].size())
	{
		for(int i = 0; i < tree[node].size(); ++i)
		{
			getEulerAndLevels(tree[node][i], nodeLevel + 1);
			eulerTree.push_back(make_pair(node, nodeLevel));
		}
	}
}
int queryLowestCommonAncestor(int firstNode, int secondNode)
{
	int firstPosition = position[firstNode];
	int secondPosition = position[secondNode];
	if(firstPosition > secondPosition)
		swap(firstPosition, secondPosition);
	int K = log2[secondPosition - firstPosition + 1];
	return minRMQ(RMQ[firstPosition][K], RMQ[secondPosition - (1 << K)][K]);
}
void buildRMQ()
{
	int N = eulerTree.size();
	for(int i = 1; i <= N; ++i)
		RMQ[i][0] = i;		
	for(int j = 1; (1 << j) <= N; ++j)
		for(int i = 0; i + (1 << j) - 1 <= N; ++i)
			RMQ[i][j] = minRMQ(RMQ[i][j - 1], RMQ[i + (1 << (j - 1))][j - 1]);
}
void buildLogarithm(int size)
{	
	log2.push_back(0);
	log2.push_back(0);
	for(int i = 2; i <= size; ++i)
		log2.push_back(log2[i/2] + 1);
}
int main()
{
	int N, M;
	ifstream in("lca.in");
	in >> N >> M;
	for(int i = 2, temp; i <= N; ++i)
	{
		in >> temp;
		tree[temp].push_back(i);
	}
	getEulerAndLevels(1, 0);
	buildLogarithm(eulerTree.size());
	buildRMQ();
	ofstream out("lca.out");
	for(int i = 0, a, b; i < M; ++i)
	{
		in >> a >> b;
		out << eulerTree[queryLowestCommonAncestor(a, b)].euler << "\n";
	}	
	in.close();
	out.close();
	return 0;
}