Cod sursa(job #2661450)

Utilizator akumariaPatrascanu Andra-Maria akumaria Data 22 octombrie 2020 00:29:08
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2 kb
#include <cstdio>
#include <vector>

using namespace std;

#define INF 1<<30;
#define MAXN 100003

vector<int> arcs[MAXN];
int euler_tour[MAXN << 4], levels[MAXN <<1], tree[MAXN <<1], first[MAXN];

int querysol, k;

void compute_euler_tour(int node, int left, int right) {
	if (left == right) {
		euler_tour[node] = left;
		return;
	}

	compute_euler_tour(node * 2, left, (left + right) / 2);
	compute_euler_tour(node * 2 + 1, (left + right) / 2 + 1, right);


	if (levels[euler_tour[node * 2]] < levels[euler_tour[node * 2 + 1]])
		euler_tour[node] = euler_tour[node * 2];
	else
		euler_tour[node] = euler_tour[node * 2 + 1];

}


void compute_levels(int node, int level) {
	tree[++k] = node;
	levels[k] = level;
	first[node] = k;

	for(vector<int>::iterator it = arcs[node].begin(); it != arcs[node].end(); ++it) {
		compute_levels(*it, level + 1);

		tree[++k] = node;
		levels[k] = level;
	}
}


void query(int node, int left, int right, int sleft, int sright) {
	if (sleft <= left && right <= sright) {
		if (levels[euler_tour[node]] < levels[euler_tour[querysol]])
			querysol = node;
		return;
	}

	if(sleft <= (left + right) / 2)
		query(node * 2, left, (left + right) / 2, sleft, sright);
	if((left + right) / 2 < sright)
		query(node * 2 + 1, (left + right) / 2 + 1, right, sleft, sright);
}


int lca(int x, int y) {
	int left, right;
	if (first[x] < first[y]) {
		left = first[x];
		right = first[y];
	} else {
		left = first[y];
		right = first[x];
	}

	querysol = 0;
	query(1, 1, k, left, right);
	return querysol;
}


int main() {
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);

	int n, m, x, y;
	scanf("%d%d", &n, &m);

	for(int i=2; i<=n; ++i) {
		scanf("%d", &x);
		arcs[x].push_back(i);
	}

	compute_levels(1, 0);
	compute_euler_tour(1, 1, k);

    levels[0] = euler_tour[0] = INF;
	for(int i=0; i<m; ++i) {
        scanf("%d%d", &x, &y);
        printf("%d\n", tree[euler_tour[lca(x, y)]]);
	}

	return 0;
}