Cod sursa(job #2287641)

Utilizator SilviuIIon Silviu SilviuI Data 22 noiembrie 2018 10:58:59
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.73 kb
#include <iostream>
#include <vector>
#define nmax 100010

using namespace std;

int n, q, c_time, nr = 0;
int v[2 * nmax], pos[nmax], lvl[nmax], e_time[nmax];
int rmq[20][2 * nmax];
vector <int> graph[nmax];

void dfs1(int node, int p)
{
	lvl[node] = lvl[p] + 1;
	e_time[node] = ++c_time;
	
	for (int i = 0; i < graph[node].size(); i++)
		if (graph[node][i] != p) dfs1(graph[node][i], node);
}

void dfs2(int node, int p)
{
	nr++; 
	pos[node] = nr;
	
	rmq[0][nr] = node;
	
	for (int i = 0; i < graph[node].size(); i++)
		if (graph[node][i] != p) {
			
			dfs2(graph[node][i], node);
			
			nr++; 
			rmq[0][nr] = node;
		}
}

void my_swap(int &a, int &b) { int aux = a; a = b; b = aux; }

int lca(int l, int r)
{
	l = pos[l];
	r = pos[r];
	
	if (l > r) my_swap(l, r);
	
	int aux = v[r - l + 1];
	int p = (1 << aux);
	
	if (lvl[rmq[aux][l]] < lvl[rmq[aux][r - p + 1]]) return rmq[aux][l]; else
		return rmq[aux][r - p + 1];
}

int main() {
	
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
	
	scanf("%d %d", &n, &q);
	
	for (int i = 2; i <= n; i++) {
		
		int x;
		
		scanf("%d", &x);
		
		graph[x].push_back(i);
		graph[i].push_back(x);
	}
	
	dfs1(1, 0); // time when entered each node
	dfs2(1, 0);
	
	v[1] = 0;
	
	for (int i = 2; i <= nr; i++) v[i] = v[i / 2] + 1;
	
	// build rmq
	for (int i = 1; (1 << i) <= nr; i++) {
		
		int aux = (1 << (i - 1));
		
		for (int j = 1; j + 2 * aux - 1 <= nr; j++)
			if (lvl[rmq[i - 1][j]] < lvl[rmq[i - 1][j + aux]]) rmq[i][j] = rmq[i - 1][j]; else
				rmq[i][j] = rmq[i - 1][j + aux];
	}
	
	for (int i = 1; i <= q; i++) {
		
		int x, y;
		
		scanf("%d %d", &x, &y);
		
		printf("%d\n", lca(x, y));
		
	}
	
	return 0;
}