Cod sursa(job #1428697)

Utilizator DuxarFII-Stefan-Negrus Duxar Data 4 mai 2015 22:20:13
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.79 kb
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

#define NMAX (100000 << 1)

int N, M, pos_euler = 1;

vector <int> euler_nodes(NMAX), level(NMAX), biggest_power2, first_found(NMAX);
vector <vector <int> > rmq, graph;

void EulerDfs(int iam, int c_level);
void PrepareRMQ();

int main() {
#ifdef INFOARENA
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
#else
	freopen("input.cpp", "r", stdin);
#endif
	
	int i, x, y, lg, p2, px, py, ans;
	
	scanf("%d %d", &N, &M);
	graph.resize(N + 1);
	for (i = 2; i <= N; ++i) {
		scanf("%d", &x);
		graph[x].push_back(i);
	}
	
	EulerDfs(1, 0);
	PrepareRMQ();
	
	for (i = 1; i <= M; ++i) {
		scanf("%d %d", &x, &y);
		px = first_found[x];
		py = first_found[y];
		if (py < px) {
			swap(px, py);
		}
		lg = py - px + 1;
		p2 = biggest_power2[lg];
		ans = rmq[p2][px];
		if (level[rmq[p2][py - (1 << p2) + 1]] < level[ans]) {
			ans = rmq[p2][py - (1 << p2) + 1];
		}
		printf("%d\n", euler_nodes[ans]);
	}
	
	
	return 0;
}

void EulerDfs(int iam, int c_level) {
	euler_nodes[pos_euler] = iam;
	level[pos_euler] = c_level;
	first_found[iam] = pos_euler;
	++pos_euler;
	
	for (auto to: graph[iam]) {
		EulerDfs(to, c_level + 1);
		euler_nodes[pos_euler] = iam;
		level[pos_euler] = c_level;
		++pos_euler;
	}
}

void PrepareRMQ() {
	
	biggest_power2.resize(pos_euler, 0);
	rmq.resize(19, vector <int> (pos_euler, 0));
	--pos_euler;
	
	int i, k, lg;
	
	rmq[0][1] = 1;
	for (i = 2; i <= pos_euler; ++i) {
		biggest_power2[i] = biggest_power2[i >> 1] + 1;
		rmq[0][i] = i;
	}
	
	for (k = 1; (1 << k) <= pos_euler; ++k) {
		lg = 1 << (k - 1);
		for (i = 1; i + (1 << k) - 1 <= pos_euler; ++i) {
			rmq[k][i] = rmq[k - 1][i];
			if (level[rmq[k - 1][i + lg]] < level[rmq[k][i]]) {
				rmq[k][i] = rmq[k - 1][i + lg];
			}
		}
	}
}