Cod sursa(job #1103556)

Utilizator dunhillLotus Plant dunhill Data 9 februarie 2014 19:37:32
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.57 kb
#include <fstream>
#include <algorithm>
using namespace std;

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

#define L (n << 1)
#define R (L | 1)

#define NMAX 100001

struct nod {
	int u;
	nod *next;
};
nod *v[NMAX];

int H[1000 * NMAX];
int level[NMAX];
int euler[NMAX];
int first[NMAX];
bool used[NMAX];

inline void add(int i, int j) {
	nod *p = new nod;
	p->u = j;
	p->next = v[i];
	v[i] = p;
}

inline int query(int n, int l, int r, int i, int j) {
	if (i <= l && r <= j) return H[n];
	int m = (l + r) >> 1;
	int sol = 0;
	if (i <= m) {
		int cnt = query(L, l, m, i, j);
		if (level[cnt] < level[sol])
			sol = cnt;
	}
	if (j > m) {
		int cnt = query(R, m + 1, r, i, j);
		if (level[cnt] < level[sol])
			sol = cnt;
	}
	return sol;
}

int K;

void DFS(int node) {
	used[node] = true;
	euler[++K] = node;
	first[node] = K;
	for (nod *it = v[node]; it; it = it->next) {
		if (!used[it->u]) {
			level[it->u] = level[node] + 1;
			DFS(it->u);
			euler[++K] = node;
		}
	}
}

void build(int n, int l, int r) {
	if (l == r){H[n] = euler[l]; return;}
	int m = (l + r) >> 1;
	build(L, l, m);
	build(R, m + 1, r);
	if (level[H[L]] < level[H[R]]) H[n] = H[L];
	else
		H[n] = H[R];
}

int i, j, N, M, T;
int X, Y;

int main() {
	fin >> N >> M;
	for (i = 2; i <= N; ++i) {
		fin >> T;
		add(i, T);
		add(T, i);
	}
	DFS(1);
	build(1, 1, K);
	level[0] = 0x3f3f3f3f;
	for (i = 1; i <= M; ++i) {
		fin >> X >> Y;
		if (first[X] > first[Y]) swap(X, Y);
		fout << query(1, 1, K, first[X], first[Y]) << '\n';
	}
	return 0;
}