Cod sursa(job #3128984)

Utilizator AlexandruIoan20Moraru Ioan Alexandru AlexandruIoan20 Data 11 mai 2023 21:30:08
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.35 kb
#include <fstream>
using namespace std; 

ifstream fin("lca.in"); 
ofstream fout("lca.out"); 

int N, M, v[250100], a[30][250100], ad[250100];

int calculareAdancime(int x) {
	if (ad[x] == -1)
		ad[x] = calculareAdancime(v[x]) + 1;
	return ad[x];
}

void generare() {
	for (int i = 1; i <= N; i++)
		ad[i] = -1; 

	for (int i = 1; i <= N; i++)
		a[1][i] = v[i];

	for (int i = 2; (1 << (i - 1)) <= N; i++) {
		for (int j = 1; j <= N; j++) {
			a[i][j] = a[i - 1][a[i - 1][j]];
		}
	}

	for (int i = 1; i <= N; i++)
		calculareAdancime(i);
};

int query(int p, int  q) {
	int nod = p;
	for (int i = 1; i <= 20; i++) {
		if (q & (1 << (i - 1))) {
			nod = a[i][nod];
		}
	}

	return nod;
}

int lca(int p, int q) {
	int answer = -1; 
	if (ad[p] < ad[q])
		q = query(q, ad[q] - ad[p]);

	else if (ad[p] > ad[q])
		p = query(p, ad[p] - ad[q]);

	if (p == q)
		return p; 

	int l = 1, r = ad[q]; 
	while (l <= r) {
		int mid = (l + r) / 2; 
		if (query(p, ad[p] - mid) == query(q, ad[q] - mid)) {
			l = mid + 1;
			answer = mid;
		}
		else
			r = mid - 1;
	}

	return query(p, ad[p] - answer); 
}


int main()
{
	fin >> N >> M; 

	for (int i = 2; i <= N; i++)
		fin >> v[i];

	generare();

	for (int i = 1; i <= M; i++) {
		int p, q; 
		fin >> p >> q; 
		fout << lca(p, q) << '\n'; 
	}


	return 0; 
}