Cod sursa(job #788949)

Utilizator mihaibogdan10Mihai Bogdan mihaibogdan10 Data 16 septembrie 2012 11:50:54
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.26 kb
#include<fstream>
#include<vector>
using namespace std;
ifstream fin("lca.in"); ofstream fout("lca.out");
int n, m, tata[100001], niv[100001], pos[100001], Log[400001], rmq[100001][20];
vector <int> fiu[100001], e;

void Parcurgere_Euler(int v){
	if (!pos[v]) pos[v] = e.size();
	niv[e.size()] = niv[e.size() - 1] + 1;
	e.push_back(v);

	for (int i = 0; i < fiu[v].size(); i++){
		Parcurgere_Euler(fiu[v][i]);
		niv[e.size()] = niv[e.size() - 1] - 1;
		e.push_back(v);
	}
}

void Build_RMQ(){
	int i, j, L;
	for (i = 0; i < e.size(); i++) rmq[i][0] = i;
	for (j = 1, L = 2; L < e.size(); L = 1 << ++j)
		for (i = 0; i < e.size() - L; i++)
			rmq[i][j] = niv[rmq[i][j-1]] < niv[rmq[i + L / 2][j - 1]] ? rmq[i][j-1] : rmq[i + L / 2][j - 1];
}

int Get_Min(int p, int q){
	if (p > q) swap(p, q);
	int l = rmq[p][Log[q - p]];
	int r = rmq[q - (1 << Log[q - p]) + 1][Log[q - p]];
	return niv[l] < niv[r] ? e[l] : e[r];
}

int main(){
	int i, v1, v2;
	fin >> n >> m;
	
	for (i = 2; i <= n; i++)
		fin >> tata[i], fiu[tata[i]].push_back(i);
	
	Parcurgere_Euler(1);
	for (Log[1] = 0, i = 2; i < e.size(); i++) Log[i] = Log[i / 2] + 1;
	Build_RMQ();
	
	for (i = 0; i < m; i++){
		fin >> v1 >> v2;
		fout << Get_Min(pos[v1], pos[v2]) << "\n";
	}
}