Cod sursa(job #3260873)

Utilizator PreparationTurturica Eric Preparation Data 3 decembrie 2024 22:20:31
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.62 kb
#include <iostream>
#include <vector>
#define MAX_N 100005
#define MAX_LOGN 20

using namespace std;

int p[MAX_N];
int d[MAX_N];
vector<int> lca;
int first[MAX_N];
int last[MAX_N];

vector<int> v[MAX_N];

// starting from first of size 2 ^ second.
int rmq[MAX_N][MAX_LOGN];
int n, m;

void prepare_lca(int root, int depth)
{
	lca.push_back(root);
	d[root] = depth;
	first[root] = ((int)lca.size()) - 1;
	last[root] = ((int)lca.size()) - 1;
	for (auto j: v[root]) {
		prepare_lca(j, depth + 1);
		lca.push_back(root);
		last[root] = ((int)lca.size()) - 1;
	}
}
// rmq now if I remember properly

int unite_rmq(int a, int b)
{
	if (d[a] < d[b])
		return a;
	return b;
}

void make_rmq_lca()
{
	for (int i = 0; i < (int) lca.size(); i++)
		rmq[i][0] = lca[i];
	for (int j = 1; (1 << j) < (int) lca.size(); j++) {
		for (int i = 0; i + (1 << j) - 1 < (int) lca.size(); i++) {
			int nxt = i + (1 << (j - 1)) - 1;
			rmq[i][j] = unite_rmq(rmq[i][j - 1], rmq[nxt][j - 1]);
		}
	}
}

int main()
{
	FILE * fin = fopen("lca.in", "r");
	FILE * fout = fopen("lca.out", "w");
	fscanf(fin, "%d %d", &n, &m);
	for (int i = 1; i < n; i++) {
		fscanf(fin, "%d", &p[i]);
		p[i]--;
		v[p[i]].push_back(i);
	}

	prepare_lca(0, 0);
	make_rmq_lca();

	for (int i = 0; i < m; i++) {
		int a, b;
		fscanf(fin, "%d %d", &a, &b);
		a--; b--;
		int pos = min(first[a], first[b]);
		int siz = max(last[a], last[b]) - pos + 1;
		int pow2 = 0;
		int lowest = lca[pos];
		while (siz != 0) {
			if (((1 << pow2) & siz) != 0)
			{
				siz -= 1 << pow2;
				lowest = unite_rmq(rmq[pos][pow2], lowest);
				pos += 1 << pow2;
			}
			pow2++;
		}
		fprintf(fout, "%d\n", lowest + 1);

	}
}