Cod sursa(job #603631)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 17 iulie 2011 21:57:49
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.38 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <stack>
#include <string.h>

#define MAXN 100000

#define DUMMY 						0x80000000
#define IS_DUMMY(node) 				((node)&DUMMY)
#define GET_NODE_FROM_DUMMY(node) 	((node)&(~DUMMY))

using namespace std;

typedef unsigned int uint32;

int E[2*MAXN+1], L[2*MAXN+1], H[MAXN], pred[MAXN+1];

// range minimum query code

int computeLog2(const uint32 num)
{
	uint32 i;

	for (i=0; 1<<i <= num; ++i) ;
	
	return i-1;
}

void preprocess(int **const mat, const int *const a, const uint32 size)
{	
	for (uint32 i=0; i<size; ++i)
		mat[i][0] = i;
	
	for (uint32 j=1; (1<<j) < size; ++j)
		for (uint32 i=0; i+(1<<j)-1 < size; ++i)
			if (a[mat[i][j-1]] <= a[mat[i+(1<<(j-1))][j-1]])
				mat[i][j] = mat[i][j-1];
			else
				mat[i][j] = mat[i+(1<<(j-1))][j-1];
}

int query(int **const mat, const int *const a, const uint32 i, const uint32 j)
{
	const uint32 l2 = j-i>0 ? computeLog2(j-i) : 0;
	
	if (a[mat[i][l2]] <= a[mat[j-(1<<l2)+1][l2]])
		return mat[i][l2];
	
	return mat[j-(1<<l2)+1][l2];
}

// compute euler path

int computeEulerTour
(	const vector<vector<int> >& tree,
	int *const E,
	int *const L,
	int *const H,
	const int *const pred,
	const int n)
{
	int count=0, e=0, l=0, h=0;
	stack<pair<int, const int> > st;
	
	st.push(make_pair(0,0));
	
	while (!st.empty())
	{
		const pair<int, const int> node = st.top();
		st.pop();
		
		if (!IS_DUMMY(node.first))
		{	
			E[e++] = node.first;
			L[l++] = node.second;
			
			H[node.first] = e-1;

			st.push(make_pair(node.first|DUMMY, node.second));
			for (int i=tree[node.first].size()-1; i>=0; --i)
			{
				st.push(make_pair(tree[node.first][i],node.second+1));
			}
		}
		else if (pred[GET_NODE_FROM_DUMMY(node.first)] != -1)
		{
			E[e++] = pred[GET_NODE_FROM_DUMMY(node.first)];
			L[l++] = node.second-1;
		}
	}
	
	/*cout << "E: ";
	for (int i=0; i<e; ++i)
	{
		cout << E[i] << " ";
	}
	cout << endl << endl;
	
	cout << "L: ";
	for (int i=0; i<l; ++i)
	{
		cout << L[i] << " ";
	}
	cout << endl << endl;
	
	cout << "H: ";
	for (int i=0; i<n; ++i)
	{
		cout << H[i] << " ";
	}
	cout << endl;*/
	
	return l;
}

int main()
{
	int n, m, l;
	int **mat;
	fstream fin("lca.in", fstream::in);
	fstream fout("lca.out", fstream::out);
	vector<vector<int> > tree;
	
	fin >> n >> m;
	//cout << n << " " << m << endl;
	
	mat = new int*[2*MAXN+1];
	for (uint32 i=0; i<2*MAXN; ++i)
	{
		mat[i] = new int[2*computeLog2(MAXN)+1];
	}
	
	/*E = new int[2*n+1];
	L = new int[2*n+1];
	H = new int[n+1];
	pred = new int[n+1];*/
	tree.resize(n);
	
	memset(H, 0xFF, n*sizeof(int)); 
	
	pred[0] = -1;
	for (int i=1; i<n; ++i)
	{
		int x;
		
		fin >> x;
		tree[x-1].push_back(i);
		pred[i] = x-1; 
	}
	
	/*for (int i=0; i<n; ++i)
	{
		cout << i << " --> ";
		for (int j=0; j<tree[i].size(); ++j)
		{
			cout << tree[i][j] << " ";
		}
		
		cout << endl;
	}
	
	for (int i=0; i<n; ++i)
	{
		cout << pred[i] << " ";
	}
	cout << endl;*/
	
	l = computeEulerTour(tree, E, L, H, pred, n);

	preprocess(mat, L, l);
	
	for (int i=0; i<m; ++i)
	{
		int u, v;
		fin >> u >> v;
		//cout << u << " " << v << endl;
		
		if (H[u-1] < H[v-1])
			fout << E[query(mat,L,H[u-1],H[v-1])]+1 << "\n";
		else
			fout << E[query(mat,L,H[v-1],H[u-1])]+1 << "\n";
	}
	
	fin.close();
	fout.close();
	return 0;
}