Cod sursa(job #2833868)

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

#define MAX_N 100000

#define EULER_SIZE (MAX_N * 2 - 1)
#define LOG_EULER_SIZE 17

int logs[EULER_SIZE + 1];

vector<int> children[MAX_N + 1];

int euler[EULER_SIZE], eulerSize;
int first[MAX_N + 1];
int level[MAX_N + 1];

int table[LOG_EULER_SIZE + 1][EULER_SIZE];

void precomputeLogs(int n) {
  int i;

  logs[1] = 0;
  for (i = 2; i <= n; ++i)
    logs[i] = logs[i / 2] + 1;
}

void dfs(int node, int lvl) {
  first[node] = eulerSize;
  euler[eulerSize] = node;
  ++eulerSize;

  level[node] = lvl;

  for (int child : children[node]) {
    dfs(child, lvl + 1);

    euler[eulerSize] = node;
    ++eulerSize;
  }
}

inline int f(int a, int b) {
  return level[a] < level[b] ? a : b;
}

void computeRmq() {
  int i, p;

  for (i = 0; i < eulerSize; ++i)
    table[0][i] = euler[i];

  for (p = 1; (1 << p) <= eulerSize; ++p)
    for (i = 0; i + (1 << p) - 1 < eulerSize; ++i)
      table[p][i] = f(table[p - 1][i], table[p - 1][i + (1 << (p - 1))]);
}

int rmqQuery(int left, int right) {
  int len, log;

  len = (right - left + 1);
  log = logs[len];

  return f(table[log][left], table[log][right - (1 << log) + 1]);
}

int lca(int a, int b) {
  a = first[a], b = first[b];
  if (a > b)
    swap(a, b);

  return rmqQuery(a, b);
}

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

  int n, m, i, father, a, b;
  fscanf(fin, "%d%d", &n, &m);
  for (i = 2; i <= n; ++i) {
    fscanf(fin, "%d", &father);
    children[father].push_back(i);
  }

  dfs(1, 0);

  precomputeLogs(eulerSize);

  computeRmq();

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

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