Cod sursa(job #1345447)

Utilizator DuxarFII-Stefan-Negrus Duxar Data 17 februarie 2015 17:07:57
Problema Lowest Common Ancestor Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 1.68 kb
#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

#define NMAX (100001 << 1)

int N, M;
int c_level, pos_rmq = 0;
vector <vector <int> > graph, rmq;
vector <int> level(NMAX), first_found, pow2;

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

int main() {
	
#ifndef INFOARENA
	freopen("input.cpp", "r", stdin);
#else
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
#endif
	
	int i, x, y, px, py, ans, right, dif;
	
	scanf("%d %d", &N, &M);
	
	graph.resize(N + 1);
	first_found.resize(N + 1, -1);
	rmq.resize(19, vector <int> (NMAX));
	
	for (i = 2; i <= N; ++i) {
		scanf("%d", &x);
		graph[x].push_back(i);
	}
	
	Euler(1, 0);
	PrepareRMQ();
	
	for (i = 0; i < M; ++i) {
		scanf("%d %d", &x, &y);
		px = first_found[x];
		py = first_found[y];
		if (py < px) {
			swap(px, py);
		}
		dif = py - px + 1;
		right = pow2[dif];
		ans = rmq[right][px];
		if (level[ans] > level[rmq[right][py - (1 << right) + 1]]) {
			ans = rmq[right][py - (1 << right) + 1];
		}
		printf("%d\n", ans);
	}
	
	return 0;
}

void Euler(int iam, int c_level) {
	rmq[0][pos_rmq] = iam;
	level[pos_rmq] = c_level;
	first_found[iam] = pos_rmq;
	++pos_rmq;
	
	for (auto to: graph[iam]) {
		Euler(to, c_level + 1);
		rmq[0][pos_rmq] = iam;
		level[pos_rmq] = c_level;
		++pos_rmq;
	}
	
	
}

void PrepareRMQ() {
	int i, right, k;
	
	pow2.resize(pos_rmq, 0);
	for (i = 2; i < pos_rmq; ++i) {
		pow2[i] = pow2[i >> 1] + 1;
	}
	
	for (k = 1; (1 << k) < pos_rmq; ++k) {
		for (i = 0; i + (1 << k) < pos_rmq; ++i) {
			rmq[k][i] = rmq[k - 1][i];
			right = 1 << (k - 1);
			if (level[first_found[rmq[k - 1][i + right]]] < level[first_found[rmq[k][i]]]) {
				rmq[k][i] = rmq[k - 1][i + right];
			}
		}
	}
}