Cod sursa(job #1462328)

Utilizator GilgodRobert B Gilgod Data 17 iulie 2015 19:43:29
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.78 kb
#include <iostream>
#include <fstream>
#include <assert.h>
#include <list>
#include <algorithm>
#include <cstring>
#include <cmath>

const char IN[] = "lca.in", OUT[] = "lca.out";
const int NMAX = 100001;
const int LOGNMAX = 17;
using namespace std;

int N, M;
int PI[NMAX];
list<int> T[NMAX];

int euler[NMAX * 2];
int depth[NMAX];
int pos[NMAX];

int discovery_time;
int RMQ[NMAX][LOGNMAX];

inline void euler_search(int node, int dpth)
{
	euler[++discovery_time] = node;
	depth[node] = dpth;
	pos[node] = discovery_time;
	for (auto &ch : T[node]) {
		euler_search(ch, dpth+1);
		euler[++discovery_time] = node;
	}
}

inline void preprocess()
{
	for (int i = 1; i <= discovery_time; ++i)
		RMQ[i][0] = i;
	for (int j = 1; (1 << j) <= discovery_time; ++j) {
		for (int i = 1; i + (1 << j) - 1 <= discovery_time; ++i) {
			if (depth[euler[RMQ[i][j - 1]]] <
				depth[euler[RMQ[i + (1 << (j - 1))][j - 1]]])
				RMQ[i][j] = RMQ[i][j - 1];
			else RMQ[i][j] = RMQ[i + (1 << (j - 1))][j - 1];
		}
	}
}

inline void read_data()
{
	assert(freopen(IN, "r", stdin)); 
	assert(freopen(OUT, "w", stdout));
	assert(scanf("%d %d", &N, &M));

	for (int i = 2; i <= N; ++i) {
		assert(scanf("%d", &PI[i]));
		T[PI[i]].push_back(i);
	}
	euler_search(1, 1);
	preprocess();
	for (int i = 1; i <= M; ++i) {
		int u, v;
		assert(scanf("%d %d", &u, &v));
		u = pos[u];
		v = pos[v];
		if (u > v) std::swap(u, v);
		int divide = (int)log2(v - u + 1);
		int lowest_ancestor = euler[RMQ[u][divide]];
		if (depth[euler[RMQ[u][divide]]] > depth[euler[RMQ[v - (1 << divide) + 1][divide]]])
			lowest_ancestor = euler[RMQ[v - (1 << divide) + 1][divide]];
		printf("%d\n", lowest_ancestor);
	}
	fclose(stdin);
	fclose(stdout);
}

int main()
{
	read_data();
	return 0;
}