Cod sursa(job #852789)

Utilizator alex_unixPetenchea Alexandru alex_unix Data 11 ianuarie 2013 18:56:00
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.79 kb

#include <cstdio>

const int MAX_N(100001);

int n, m;
int level [MAX_N];
int log [MAX_N << 1];
int rmq [18] [MAX_N << 1], index(1);
int start [MAX_N];

struct list
{
	int node;
	struct list *next;
} *graph [MAX_N];

inline void add (int x, int y)
{
	struct list *new_edge(new struct list);
	new_edge->node = y;
	new_edge->next = graph[x];
	graph[x] = new_edge;
}

void DepthFirstSearch (int node, int depth)
{
	start[node] = index;
	rmq[0][index] = node;
	++index;
	level[node] = depth;
	for (struct list *iterator(graph[node]) ; iterator ; iterator = iterator->next)
	{
		DepthFirstSearch(iterator->node,depth + 1);
		rmq[0][index] = node;
		++index;
	}
}

inline int min (int a, int b)
{
	return level[a] < level[b] ? a : b;
}

inline void initialize (void)
{
	--index;
	int i, j;
	for (i = 2 ; i <= index ; ++i)
		log[i] = log[i >> 1] + 1;
	for (i = 1 ; i <= log[index] ; ++i)
		for (j = 1 ; j <= index - (1 << i) + 1 ; ++j)
			rmq[i][j] = min(rmq[i - 1][j],rmq[i - 1][j + (1 << (i - 1))]);
}

inline void swap (int &a, int &b)
{
	int temp(a);
	a = b;
	b = temp;
}

inline int RangeMinimumQuery (int x, int y)
{
	int cardinal(y - x + 1);
	return min(rmq[log[cardinal]][x],rmq[log[cardinal]][y - (1 << log[cardinal]) + 1]);
}

inline int LowestCommonAncestor (int x, int y)
{
	x = start[x];
	y = start[y];
	if (x > y)
		swap(x,y);
	return RangeMinimumQuery(x,y);
}

int main (void)
{
	std::freopen("lca.in","r",stdin);
	std::freopen("lca.out","w",stdout);
	std::scanf("%d %d",&n,&m);
	for (int counter(2), father ; counter <= n ; ++counter)
	{
		std::scanf("%d",&father);
		add(father,counter);
	}
	DepthFirstSearch(1,0);
	initialize();
	for (int counter(0), x, y ; counter < m ; ++counter)
	{
		std::scanf("%d %d",&x,&y);
		std::printf("%d\n",LowestCommonAncestor(x,y));
	}
	std::fclose(stdin);
	std::fclose(stdout);
	return 0;
}