Cod sursa(job #1903341)

Utilizator BonCipBonciocat Ciprian Mircea BonCip Data 5 martie 2017 10:20:43
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.99 kb
#include <stdio.h>

struct node {
	int v;
	node *n;
};
node* all() {
	static int sp = 1000;
	static node* st = NULL;
	if (sp == 1000) {
		sp = 0;
		st = new node[1000];
	}
	return st + (sp++);
}

namespace Var {
	FILE *fin, *fout;
	int N, M;
	node **G;
	int e, *euler;
	int *lvl, *fi;
	int *lg, **m;
};

void citire() {
	using namespace Var;
	fscanf(fin, "%d%d", &N, &M);
	G = new node*[N + 1]();
	for (int i = 2; i <= N; ++i) {
		int x;
		fscanf(fin, "%d", &x);
		node *edge = all();
		edge->v = i;
		edge->n = G[x];
		G[x] = edge;
	}
	euler = new int[2*N - 1];
	lvl = new int[N + 1];
	fi = new int[N + 1];
}
void f_euler(int u = 1, int dep = 0) {
	using namespace Var;
	lvl[u] = dep;
	fi[u] = e;
	euler[e++] = u;
	for (node* it = G[u]; it; it = it->n) {
		f_euler(it->v, dep + 1);
		euler[e++] = u;
	}
}
int mi(int x, int y) {
	using namespace Var;
	return (lvl[euler[x]] < lvl[euler[y]] ? x : y);
}
void pre_rmq() {
	using namespace Var;
	// Fac vectorul lg
	lg = new int[e + 1];
	lg[1] = 0;
	for (int i = 2; i <= e; ++i) {
		lg[i] = 1 + lg[i / 2];
	}
	// Fac tabloul m
	m = new int*[lg[e] + 1];
	for (int i = 0; i <= lg[e]; ++i) {
		m[i] = new int[e];
	}
	for (int i = 0; i <= e; ++i) {
		m[0][i] = i;
	}
	for (int i = 1; i <= lg[e]; ++i) {
		for (int j = 0; j < e; ++j) {
			if (j + (1 << (i-1)) < e) {
				m[i][j] = mi(m[i-1][j], m[i-1][j + (1<<(i-1))]);
			} else {
				m[i][j] = m[i-1][j];
			}
		}
	}
}
int rmq(int l, int r) {
	using namespace Var;
	return mi(m[lg[r - l + 1]][l], m[lg[r - l + 1]][r - (1 << lg[r-l+1]) + 1]);
}
int lca(int x, int y) {
	using namespace Var;
	if (fi[x] < fi[y]) {
		return euler[rmq(fi[x], fi[y])];
	} else {
		return euler[rmq(fi[y], fi[x])];
	}
}
void afisare() {
	using namespace Var;
	for (int i = 0; i < M; ++i) {
		int x, y;
		fscanf(fin, "%d%d", &x, &y);
		fprintf(fout, "%d\n", lca(x, y));
	}
}

int main()
{
	using namespace Var;
	fin = fopen("lca.in", "r");
	fout = fopen("lca.out", "w");
	
	citire();
	f_euler();
	pre_rmq();
	afisare();
	
	fclose(fin);
	fclose(fout);
	return 0;
}