Pagini recente » Cod sursa (job #1094897) | Cod sursa (job #2397407) | Cod sursa (job #180124) | Cod sursa (job #3212113) | Cod sursa (job #2312482)
/*
* 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;
}