Cod sursa(job #2312482)

Utilizator dragomir_ioanDragomir Ioan dragomir_ioan Data 4 ianuarie 2019 22:27:51
Problema Lowest Common Ancestor Scor 100
Compilator c-64 Status done
Runda Arhiva educationala Marime 2.58 kb
/*
 * Lowest Common Ancestor
 * https://infoarena.ro/problema/lca
 *
 * RMQ over Euler Tour ( https://en.wikipedia.org/wiki/Euler_tour_technique )
 * 
 */

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define MAXN 100002

int *fii[MAXN], grad[MAXN];
int tour_node[2*MAXN], tour_depth[2*MAXN], tour_size = 0;
int first_index_of[MAXN];

inline void add_to_tour(int node, int depth) {
	tour_size++;

	tour_node[tour_size] = node;
	tour_depth[tour_size] = depth;

	if(first_index_of[node] == 0)
		first_index_of[node] = tour_size;
}

void do_tour(int node, int depth) {
	add_to_tour(node, depth);

	bool a_avut_fii = false;
	for(int i=0; i<grad[node]; i++) {
		do_tour(fii[node][i], depth+1);
		add_to_tour(node, depth);
	}
}

inline int Min(int a, int b) {
	return a < b ? a : b;
}

int n;
int logn;
int mintable[19][2*MAXN];

inline void rmq_init() {
	for(int i=1; i<=tour_size; i++) {
		mintable[0][i] = i;
	}

	for(int spacing=1; spacing < logn; spacing++) {
		int lastjmp = 1 << (spacing-1);
		for(int i=1; i<=tour_size-lastjmp; i++) {
			int st_i = mintable[spacing-1][i], dr_i = mintable[spacing-1][i + lastjmp],
				st_d = tour_depth[st_i], dr_d = tour_depth[dr_i];

			if(st_d < dr_d) {
				mintable[spacing][i] = st_i;
			} else {
				mintable[spacing][i] = dr_i;
			}
		}
	}
}


inline int rmq_query(int st, int dr) {
	int dist = dr - st + 1;
	int spacing = logn;
	while(spacing > 0 && (1 << spacing) >= dist) spacing--;

	int st_i = mintable[spacing][st], dr_i = mintable[spacing][dr - (1<<spacing) + 1],
		st_d = tour_depth[st_i], dr_d = tour_depth[dr_i];

	if(st_d < dr_d) {
		return tour_node[st_i];
	} else {
		return tour_node[dr_i];
	}
}

int main() {
	int i, m, tata;

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

	// Citire 2-pass for no particular reason other than just showing off :D
	scanf("%d%d", &n, &m);

	for(i=2; i<=n; i++) {
		scanf("%d", &tata);
		grad[tata]++;
	}
	for(i=1; i<=n; i++) {
		fii[i] = malloc(grad[i] * sizeof(int));
		grad[i] = 0;
	}

	fseek(stdin, 0, SEEK_SET);

	scanf("%d%d", &n, &m);
	for(i=2; i<=n; i++) {
		scanf("%d", &tata);
		fii[tata][grad[tata]++] = i;
	}

	do_tour(1, 0);
	while((1 << logn) <= tour_size) logn++;
	rmq_init();
	/*for(i=0; i<logn; i++) {
		fprintf(stderr, "2^%d:", i);
		for(int j=1; j<=tour_size - (1 << i) + 1; j++) {
			fprintf(stderr, "% 3d", mintable[i][j]);
		}
		fprintf(stderr, "\n");
	}*/

	for(i=1; i<=m; i++) {
		int a, b;
		scanf("%d%d", &a, &b);
		int st = first_index_of[a],
			dr = first_index_of[b];
		if(st > dr) {
			int aux = st;
			st = dr;
			dr = aux;
		}

		printf("%d\n", rmq_query(st, dr));
	}

	return 0;
}