Cod sursa(job #632932)

Utilizator mihai0110Bivol Mihai mihai0110 Data 12 noiembrie 2011 15:47:06
Problema Lowest Common Ancestor Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 1.88 kb
#include <fstream>
#include <iostream>
#include <vector>

#define MAXN 100001
#define MAXRMQ 50

#define min(a, b) (a) < (b) ? a : b
#define max(a, b) (a) > (b) ? a : b

using namespace std;

vector<int> tree[MAXN];
int first_appearance_index[MAXN];
vector<int> euler_level;
vector<int> euler_node;
int rmq[MAXRMQ][MAXN * 3];

void calculate_euler(int node, int level) {
	static int index = 0;

	first_appearance_index[node] = index++;
	euler_level.push_back(level);
	euler_node.push_back(node);

	for(unsigned int i = 0; i < tree[node].size(); i++) {
		calculate_euler(tree[node][i], level + 1);
		index++;
		euler_level.push_back(level);
		euler_node.push_back(node);
	}
}

void precalculate_rmq() {
	for(unsigned int j = 0; j < euler_level.size(); j++)
		rmq[0][j] = j;
	
	for(int i = 1; (1 << i) <= euler_level.size(); i++)
		for(unsigned int j = 0; j <= euler_level.size() - (1 << i); j++) {
			rmq[i][j] = rmq[i - 1][j + (1 << (i - 1))];
			if (euler_level[rmq[i - 1][j]] < euler_level[rmq[i][j]])
				rmq[i][j] = rmq[i - 1][j];
		}
}

int get_rmq_min(int index1, int index2) {
	int distance = index2 - index1 + 1;
	int exp, power;
	for(exp = 1, power = 0; exp < distance; power++, exp<<=1);

	exp >>= 1;
	power--;

	return euler_level[rmq[power][index1]] < euler_level[rmq[power][index2 - exp]] ? rmq[power][index1] : rmq[power][index2 - exp];
	
}

int main(void) {
	ifstream f("lca.in");
	ofstream g("lca.out");
	
	int nodes, queries;
	f >> nodes >> queries;
	
	int father;
	for (int i = 1; i < nodes; i++) {
		f >> father;
		tree[father].push_back(i + 1);
	}

	calculate_euler(1, 0);
	precalculate_rmq();

	int node1, node2;
	int index1, index2;
	while(queries--) {
		f >> node1 >> node2;
		index1 = min(first_appearance_index[node1], first_appearance_index[node2]);
		index2 = max(first_appearance_index[node1], first_appearance_index[node2]);
		g << euler_node[get_rmq_min(index1, index2)] << '\n';
	}

	return 0;
}