Cod sursa(job #830903)

Utilizator horeste12Stoianovici Horatiu Andrei horeste12 Data 7 decembrie 2012 20:39:51
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.39 kb
#include <cstdio>
#include <vector>
#include <malloc.h>
#include <cmath>
using namespace std;

#define mn(a, b) compare(a, b) < 0? a : b;

int *level;

int log2(int x)
{
	return (int)(log(x) / log(2));
}

int rmq(int x, int y, int *vect, int lg1, int (*compare) (int x, int y))
{
	static int *lg, **rmq, n, *a = NULL;
	static int lMax;
	int l, diff, sh;

	if(x > y)
		swap(x, y);

	if(vect != a)
	{
		a = vect;
		n = lg1;

		//memory allocation
		lg = (int *) malloc((n + 1) * sizeof(int));
		lMax = log2(n) + 1;
		rmq = (int **) malloc((lMax + 1) * sizeof(int*));
		for(int i = 0; i <= lMax; i++)
			rmq[i] = (int *) malloc((n + 1) * sizeof(int*));

		//computing the values
		lg[1] = 0;
		for (int i = 2; i <= n; i++)
			lg[i] = lg[i/2] + 1;

		for (int i = 1; i <= n; i++)
			rmq[0][i]= a[i];

		for (int i=1; (1 << i) <= n;i++)
		{
			for (int j = 1; j <= n - (1 << i) + 1; j++)
			{
				l = 1 << (i - 1);
				rmq[i][j]= mn(rmq[i-1][j] , rmq[i-1][j+l]);
			}
		}
	}

	//calculating required Range Minimum Query
	diff = y - x + 1;
	l = lg[diff];
	sh = diff - (1 << l);
	return mn(rmq[l][x], rmq[l][x+sh]);
}

int comp(int a, int b)
{
	if(level[a] < level[b])
		return -1;
	if(level[a] > level[b])
		return 1;
	return 0;
}

void parcurgereEuler(vector<int> *euler, vector<int> *G, int *position, int *level, int current, bool *viz)
{
	viz[current] = true;
	(*euler).push_back(current);
	position[current] = (*euler).size();
	for(vector<int>::iterator i = G[current].begin(); i < G[current].end(); i++)
	{
		if(!viz[*i])
		{
			level[*i] = level[current] + 1;
			parcurgereEuler(euler, G, position, level, *i, viz);
			(*euler).push_back(current);
		}
	}
}

int main()
{
	freopen("lca.in","r",stdin);
	freopen("lca.out","w",stdout);

	vector<int> euler;
	int *position;
	int n, m, a, b, father;
	bool *visited;
	vector<int> *G;

	scanf("%d%d", &n, &m);

	visited = (bool*) calloc(n + 1, sizeof(bool));
	position = (int*) calloc(n + 1, sizeof(int));
	level = (int*) calloc(n + 1, sizeof(int));

	G = new vector<int>[n + 1];

	for(int i = 2; i <= n; i++)
	{
		scanf("%d", &father);
		G[father].push_back(i);
	}

	parcurgereEuler(&euler, G, position, level, 1, visited);

	for(int i = 1; i <= m; i++)
	{
		scanf("%d%d", &a, &b);
		printf("%d\n", rmq(position[a], position[b], euler.data() - 1, euler.size(), comp));
	}

	return 0;
}