Cod sursa(job #3312485)

Utilizator ViAlexVisan Alexandru ViAlex Data 28 septembrie 2025 17:04:24
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.1 kb
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;

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

struct node {
	int index;
	int height;
};

vector<node> euler;
vector<vector<int>> graph;
vector<int> first_index;
int n, m;

void read(){
	in>>n>>m;
	graph.resize(n+1);
	int father;

	for (int i = 2; i<=n; i++){
		in>>father;	
		graph[i].push_back(father);
		graph[father].push_back(i);
	}
}

void dfs(int here, int father, int depth) {
	euler.push_back({here, depth});

	for(int neighbour: graph[here]) {
		if (neighbour == father) continue;

		dfs(neighbour, here, depth+1);
		euler.push_back({here, depth});
	}
}

vector<node> tree;
void build_tree_rec(int index, int l, int r) {
	if(l == r) {
		tree[index] = euler[l];
	} else {
		int m = (l+r)/2;
		build_tree_rec(index*2, l, m);
		build_tree_rec(index*2+1, m+1, r);
		
		node left = tree[index*2];
		node right = tree[index*2 + 1];

		if (left.height < right.height) {
			tree[index] = left;
		} else {
			tree[index] = right;
		}
	}
}

void build_tree() {
	tree.resize(4 * euler.size());
	build_tree_rec(1, 0, euler.size()-1);
}


node query_tree_rec(int index, int l, int r, int ql, int qr) {
	if (l>= ql && r <= qr) {
		return tree[index];
	} else {
		int m = (l+r)/2;
		node result = {-1, (int) 1e9};

		if(ql <= m) {
			node k = query_tree_rec(index*2, l, m, ql, qr);
			if (k.height < result.height) result = k;
		}

		if (qr > m) {
			node k = query_tree_rec(index*2+1, m+1, r, ql, qr);
			if (k.height < result.height) result = k;
		}

		return result;
	}
}

void compute_first_indices() {
	first_index.resize(n+1, -1);
	for(int i = 0 ;i<euler.size(); i++){
		node here = euler[i];
		if (first_index[here.index] == -1) {
			first_index[here.index] = i;
		} 
	}
}

int lca(int a, int b){
	int index_a = first_index[a];
	int index_b = first_index[b];
	if (index_a > index_b) swap(index_a, index_b);

	node result = query_tree_rec(1, 0, euler.size()-1, index_a, index_b);
	return result.index;
}

int main(){
	read();
	dfs(1, 0, 0);
	build_tree();
	compute_first_indices();

	int a, b;
	for(int i = 0; i<m;i++){
		in>>a>>b;
		out<<lca(a, b)<<"\n";
	}
	return 0;
}