Cod sursa(job #2274793)

Utilizator TincaMateiTinca Matei TincaMatei Data 2 noiembrie 2018 15:05:32
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.84 kb
#include <cstdio>
 
const int MAX_N = 100000;
const int MAX_RMQ = 2 * MAX_N - 1;
const int MAX_LOG = 17;
 
int first[1+MAX_N];
int last[1+MAX_N];
int next[1+MAX_N];
int v[1+MAX_N];
int edge = 1;
 
int f[1+MAX_N];
int top = 0;
int rmq[MAX_RMQ][1+MAX_LOG];
int log[1+MAX_RMQ];
int p2[1+MAX_LOG];
int dep[1+MAX_N];
 
void addToList(int nod, int x) {
  v[edge] = x;
  if(first[nod] == 0)
    first[nod] = last[nod] = edge;
  else
    last[nod] = next[last[nod]] = edge;
  edge++;
}
 
void addNod(int nod, int depth) {
  dep[nod] = depth;
  if(f[nod] == 0)
    f[nod] = top;
  rmq[top][0] = nod;
  top++;
}
 
void dfs(int nod, int depth) {
  int i;
  addNod(nod, depth);
  i = first[nod];
  while(i != 0) {
    dfs(v[i], depth + 1);
    addNod(nod, depth);
    i = next[i];
  }
}
 
void computeRMQ(int n) {
  int i, l;
  n = 2 * n - 1;
  for(l = 1; l <= log[n]; l++) {
    for(i = 0; i < n - p2[l] + 1; i++) {
      if(dep[rmq[i][l - 1]] < dep[rmq[i + p2[l-1]][l - 1]])
        rmq[i][l] = rmq[i][l - 1];
      else
        rmq[i][l] = rmq[i + p2[l-1]][l - 1];
    }
  }
}
 
int getMin(int a, int b) {
  int aux, l;
  if(a > b) {
    aux = a;
    a = b;
    b = aux;
  }
  l = log[b - a + 1];
  if(dep[rmq[a][l]] < dep[rmq[b - p2[l] + 1][l]])
    return rmq[a][l];
  else
    return rmq[b - p2[l] + 1][l];
}
 
int main() {
  int n, m, i, father, p, j, a, b;
 
  p = 1;
  j = 0;
  for(i = 1; i <= MAX_RMQ; i++) {
    if(i == p) {
      p2[j] = p;
      p = p * 2;
      j++;
    }
    log[i] = j - 1;
  }
 
  FILE *fin = fopen("lca.in", "r");
  fscanf(fin, "%d%d", &n, &m);
  for(i = 2; i <= n; i++) {
    fscanf(fin, "%d", &father);
    addToList(father, i);
  }
  dfs(1, 0);
  computeRMQ(n);
  FILE *fout = fopen("lca.out", "w");
  for(i = 0; i < m; i++) {
    fscanf(fin, "%d%d", &a, &b);
    fprintf(fout, "%d\n", getMin(f[a], f[b]));
  }
  fclose(fin);
  fclose(fout);
  return 0;
}