Cod sursa(job #2833798)

Utilizator Teodor94Teodor Plop Teodor94 Data 15 ianuarie 2022 18:38:20
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.5 kb
#include <stdio.h>
#include <algorithm>
using namespace std;

#define MAX_N 100000
#define LOG_N 17

int level[MAX_N + 1];
int father[LOG_N][MAX_N + 1];

inline int log2(int x) {
  int log;

  log = 0;
  while (x > 1)
    x >>= 1, ++log;

  return log;
}

inline int computeLevel(int node) {
  if (node == 1)
    return 0;

  if (!level[node])
    level[node] = computeLevel(father[0][node]) + 1;

  return level[node];
}

int lca(int a, int b) {
  int j;

  if (level[a] > level[b])
    swap(a, b);

  if (level[a] < level[b]) {
    j = log2(level[b] - level[a]);
    while (j >= 0 && level[b] > level[a]) {
      if (level[b] - (1 << j) >= level[a])
        b = father[j][b];
      --j;
    }
  }

  if (a != b) {
    for (j = log2(level[a]); j >= 0; --j)
      if (father[j][a] && father[j][a] != father[j][b])
        a = father[j][a], b = father[j][b];

    a = b = father[0][a];
  }

  return a;
}

int main() {
  FILE *fin, *fout;
  fin = fopen("lca.in", "r");
  fout = fopen("lca.out", "w");

  int n, m, i, lvl, a, b;
  fscanf(fin, "%d%d", &n, &m);
  for (i = 2; i <= n; ++i)
    fscanf(fin, "%d", &father[0][i]);

  for (i = 2; i <= n; ++i)
    level[i] = computeLevel(i);

  for (lvl = 1; (1 << lvl) < n; ++lvl)
    for (i = 2; i <= n; ++i)
      father[lvl][i] = father[lvl - 1][father[lvl - 1][i]];

  while (m--) {
    fscanf(fin, "%d%d", &a, &b);
    fprintf(fout, "%d\n", lca(a, b));
  }

  fclose(fin);
  fclose(fout);
  return 0;
}