Cod sursa(job #2661455)

Utilizator akumariaPatrascanu Andra-Maria akumaria Data 22 octombrie 2020 02:04:16
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.62 kb
#include <cstdio>
#include <vector>

using namespace std;

#define MAXN 100004

int k, n;

int first[MAXN], levels[MAXN * 2], euler[MAXN * 2], logs[MAXN << 1];
int rmq[20][MAXN << 2];
vector<vector<int>> arcs;



void get_levels(int node, int level) {
	levels[++k] = level;
	euler[k] = node;
	first[node] = k;


	for(int i=0; i<arcs[node].size(); ++i) {
		get_levels(arcs[node][i], level + 1);

		levels[++k] = level;
		euler [k] = node;
	}
}


void compute_rmq() {
	for(int i=2; i<=k; ++i)
		logs[i] = logs [i / 2] + 1;

	for(int i=0; i<=k; ++i)
		rmq[0][i] = i;


	for(int i=1; (1<<i) < k; ++i)
		for(int j=1; j <=  k - (1<<i); ++j) {
			int leftover = 1 << (i-1);

			rmq[i][j] = rmq[i-1][j];

			if (levels[rmq[i-1][j + leftover]] < levels[rmq[i][j]])
				rmq[i][j] = rmq[i-1][j+leftover];
		}
}


int query(int x, int y) {
	int diff;
	int left, right;
	if (first[x] < first[y]) {
		left = first[x];
		right = first[y];
	} else {
		left = first[y];
		right = first[x];
	}

	diff = right - left + 1;
	int sol = rmq[logs[diff]][left];
	int leftover = diff - (1<< logs[diff]);

	if (levels[sol] > levels[rmq[logs[diff]][left + leftover]])
		sol = rmq[logs[diff]][left + leftover];

	return euler[sol];
}




int main() {
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);

	int m, x, y;
	scanf("%d%d", &n, &m);
	arcs.resize(n+2);


	for(int i=2; i<=n; ++i) {
		scanf("%d", &x);
		arcs[x].push_back(i);
	}

	get_levels(1, 0);
	compute_rmq();

	for(int i=0; i<m; ++i) {
		scanf("%d%d", &x, &y);
		printf("%d\n", query(x, y));
	}

	return 0;
}