Cod sursa(job #2729743)

Utilizator cristi_macoveiMacovei Cristian cristi_macovei Data 25 martie 2021 10:55:44
Problema Lowest Common Ancestor Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.61 kb
#include <iostream>
#include <fstream>
#include <cassert>

const int LOG = 16;
const int NMAX = 1e5;

int t[1 + NMAX][1 + LOG];
int level[1 + NMAX];

inline int ancestor(int node, int depth) {
  int e = 0;
  while (depth) {
    if (depth & 1)
      node = t[node][e];

    ++e;
    depth >>= 1;
  }

  return node;
}

int calc_level(int i) {
  if (level[t[i][0]] != 0)
    level[i] = 1 + level[t[i][0]];
  else
    level[i] = 1 + calc_level(t[i][0]);

  return level[i];
}

int main() {
  std::ifstream in("lca.in");
  std::ofstream out("lca.out");

  int n, m;
  in >> n >> m;

  for (int i = 2; i <= n; ++i)
    in >> t[i][0];
  t[1][0] = 0;

  level[1] = 1;
  for (int i = 2; i <= n; ++i)
    level[i] = calc_level(i);

  for (int i = 1; i <= n; ++i) {
    for (int e = 1; e <= LOG; ++e)
      t[i][e] = t[t[i][e - 1]][e - 1];
  }

  for (int i = 1; i <= m; ++i) {
    int a, b;
    in >> a >> b;

    if (level[a] < level[b])
      std::swap(a, b);

    int level_diff = level[a] - level[b];
    a = ancestor(a, level_diff);

//    int j = 0;
//    while (ancestor(a, j) != ancestor(b, j)) {
//      std::cout << "ancestor of a = " << a << " at depth " << j << " is " << ancestor(a, j) << '\n';
//      std::cout << "ancestor of b = " << b << " at depth " << j << " is " << ancestor(b, j) << '\n';
//      ++j;
//    }

    int left = 0, right = n, mid, ans = -1;
    while (left <= right) {
      mid = (left + right) / 2;

      if (ancestor(a, mid) == ancestor(b, mid)) {
        ans = mid;
        right = mid - 1;
      }
      else
        left = mid + 1;
    }

    assert(ans != -1);
    out << ancestor(a, ans) << '\n';
  }

  return 0;
}