Cod sursa(job #739639)

Utilizator ColcerPColcer Paul ColcerP Data 23 aprilie 2012 16:34:04
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.48 kb
#include<fstream>
#include<vector>
using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

#define MAX 200100

int n, m, RMQ[20][MAX];
int euler[MAX], nivel[MAX];

vector<int> vec[MAX];

void dfs(int);
void rmq();
int query(int, int);

int main()
{
	int a, b;
	f>>n>>m;	// read number of nodes and number of pairs
	
	for(int i = 2; i <= n; ++i)	// go through next n-1 numbers which represent every node except the root
	{
		f>>a;		// read the node
		vec[a].push_back(i);	// create parent tree
	}
	
	dfs(1);
	rmq();
	
	for(int i = 1; i <= m; ++i)	// solve lca's for pairs
	{
		f>>a>>b;					// read pair of nodes
		g<<query(a, b)<<"\n";	// write least common ancestor in output file
	}
	
	f.close();
	g.close();
	return 0;
}

void dfs(int nod)
{
	int i;
	euler[++euler[0]]=nod;		// add current node to euler representation of tree
	nivel[nod] = euler[0];
	for(i = 0; i < (int)vec[nod].size(); ++i)
	{
		dfs(vec[nod][i]);
		euler[++euler[0]] = nod;
	}
	
}

void rmq()
{	
	// in rmq[i][j] we retain the minimal level between the positions (j, j + 2*i - 1) from the euler representation
	for(int i = 1; i < euler[0]; ++i)
		RMQ[0][i] = euler[i];
	
	for(int i = 1; (1 << i) <= euler[0]; ++i)
		for(int j = 1; j<= euler[0] - (1<<i) + 1; ++j)
			RMQ[i][j] = min(RMQ[i-1][j], RMQ[i-1][j + (1 << (i-1))]);
			
	
}

int query(int a, int b)
{
	int x, y, i;
	x = nivel[a];
	y = nivel[b];
	
	if( x > y ) swap(x, y);
	
	for( i = 1; (1 << i) <= (y-x+1); ++i);
		--i;
	return min(RMQ[i][x], RMQ[i][y - (1 << i) + 1]);
}