Cod sursa(job #1605139)

Utilizator TeodorCotetCotet Teodor TeodorCotet Data 18 februarie 2016 19:50:13
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.8 kb
#include <bits/stdc++.h>

using namespace std;

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

#define pair pair<int,int>

const int NMAX = 100000;
const int MMAX = 2000000;
const int H = 18;

int n; int m;

vector<int> g[NMAX + 1];

int euler[NMAX * 2]; int cnt;
int lev[NMAX * 2];
int rmq[H][NMAX * 2]; //rmq[i][j] = min(v[j] ... v[j + (1 << i) - 1]) inclusiv
int lg[NMAX * 2]; //lg[i] cel mai mare nr x ai 2 ^ x <= i
//ficare muchie vine cu 2 noduri, avem 2 * (n - 1) muchii + 1 pentru radacina + 1 indexare de la 1 => n * 2

vector<int> first(NMAX + 1, 0);

void read() {

	fin >> n >> m;
	
	for(int i = 2; i <= n; ++i) {

		int x; fin >> x;

		g[x].push_back(i);
	}
}

void dfsEuler(int x, int level) {

	euler[++cnt] = x;
	lev[cnt] = level;
	first[x] = cnt;

	for(int node : g[x])  {
			dfsEuler(node, level + 1);
			euler[++cnt] = x;
			lev[cnt] = level;
		}
		
}

void constructRmq() {

	for(int i = 1; i <= cnt; ++i)
		rmq[0][i] = i;

	for(int i = 1; (1 << i) <= cnt; ++i)
		for(int j = 1; j + (1 << i) - 1 <= cnt; ++j) {

			rmq[i][j] = rmq[i - 1][j];
			if(lev[rmq[i][j]] > lev[ rmq[i - 1][j + ( 1 << (i - 1) )] ])
				rmq[i][j] = rmq[i - 1][j + ( 1 << (i - 1) )];

		}

	lg[1] = 0;

	for(int i = 2; i <= cnt; ++i)
		lg[i] = lg[i/2] + 1;
}

int lca(int x, int y) {
	
	if(first[x] > first[y]) swap(x, y);

	int dim = first[y] - first[x] + 1;
	int lgDim = lg[dim];

	int sol = rmq[lgDim][first[x]];


	if(lev[sol] > lev[ rmq[lgDim][ first[y] - (1 << lgDim) + 1] ])
		sol = rmq[lgDim][ first[y] - (1 << lgDim) + 1];

	return euler[sol];
}

void solve() {

	dfsEuler(1, 0);
	constructRmq();

	while(m--) {

		int x; int y;
		fin >> x >> y;

		fout << lca(x, y) << '\n'; 
	}

}


int main() {

	read();

	solve();

	return 0;
}