Cod sursa(job #2097105)

Utilizator flibiaVisanu Cristian flibia Data 30 decembrie 2017 15:29:16
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 1.52 kb
#include <bits/stdc++.h>
#define N 100100
#define L 2 * pos
#define R 2 * pos + 1

using namespace std;

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

int n, m, x, y, vf, d[N], poz[N], stk[N << 3], h_min[N << 3], h_lca[N << 3];
vector <int> v[N];
bool viz[N], seen[N];

void dfs(int from, int lvl){
	viz[from] = 1;
	stk[++vf] = from;
	d[from] = lvl;
	if(!seen[from]){
		poz[from] = vf;
		seen[from] = 1;
	}
	for(auto to : v[from]){
		if(!viz[to])
			dfs(to, lvl + 1);
		stk[++vf] = from;
	}
}

void build(int st, int dr, int pos){
	if(st == dr){
		h_min[pos] = d[stk[st]];
		h_lca[pos] = stk[st];
		return;
	}
	int mid = st + dr >> 1;
	build(st, mid, L);
	build(mid + 1, dr, R);
	if(h_min[L] <= h_min[R]){
		h_min[pos] = h_min[L];
		h_lca[pos] = h_lca[L];
	} else{
		h_min[pos] = h_min[R];
		h_lca[pos] = h_lca[R];
	}
}

pair <int, int> query(int st, int dr, int pos, int l, int r){
	if(l <= st && dr <= r)
		return {h_min[pos], h_lca[pos]};
	int mid = st + dr >> 1;
	pair <int, int> left = {2e9, 1};
	pair <int, int> right = {2e9, 1};
	if(l <= mid)
		left = query(st, mid, L, l, r);
	if(r > mid)
		right = query(mid + 1, dr, R, l, r);
	if(left.first <= right.first)
		return left;
	else 
		return right;
}

int main(){
	in >> n >> m;
	for(int i = 2; i <= n; i++){
		in >> x;
		v[x].push_back(i);
	}
	dfs(1, 0);
	build(1, vf, 1);
	while(m--){
		in >> x >> y;
		x = poz[x];
		y = poz[y];
		if(x > y)
			swap(x, y);
		out << query(1, vf, 1, x, y).second << '\n';
	}
	return 0;
}