Cod sursa(job #2730930)

Utilizator cristi_macoveiMacovei Cristian cristi_macovei Data 27 martie 2021 00:38:35
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.97 kb
#include <iostream>
#include <fstream>
#include <vector>

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

int euler_len = 0;
int rmq[1 + 2 * NMAX][1 + LOG];

std::vector<int> graph[1 + NMAX];
int level[1 + NMAX];
int first_ap[1 + NMAX];
int last_p2[1 + NMAX];

void euler_repr(int node, int depth) {
  rmq[++euler_len][0] = node;
  level[node] = depth;
  first_ap[node] = euler_len;

  for (int next: graph[node]) {
    euler_repr(next, depth + 1);

    rmq[++euler_len][0] = node;
    level[node] = depth;
  }
}

inline void build_rmq() {
  for (int depth = 1; depth <= LOG; ++depth) {
    for (int i = 1; i <= euler_len - (1 << depth) + 1; ++i) {
      int min_left = rmq[i][depth - 1];
      int min_right = rmq[i + (1 << (depth - 1))][depth - 1];

      if (level[min_left] < level[min_right])
        rmq[i][depth] = min_left;
      else
        rmq[i][depth] = min_right;
    }
  }
}

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

  int exp = 1;
  for (int i = 1; i <= NMAX; ++i) {
    if ((1 << (exp + 1)) <= i)
      ++exp;

    last_p2[i] = exp;
  }

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

  for (int i = 2; i <= n; ++i) {
    int t;
    in >> t;

    graph[t].push_back(i);
  }

  euler_repr(1, 1);

  build_rmq();

//  for (int i = 1; i <= euler_len; ++i)
//    std::cout << rmq[i][0] << ' ';
//  std::cout << '\n';
//
//  for (int i = 1; i <= euler_len; ++i) {
//    std::cout << rmq[i][0] << ": ";
//    for (int j = 0; j <= LOG; ++j)
//      std::cout << rmq[i][j] << ' ';
//    std::cout << '\n';
//  }

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

    if (first_ap[a] == first_ap[b]) {
      out << a << '\n';
      continue;
    }

    a = first_ap[a];
    b = first_ap[b];

    if (a > b)
      std::swap(a, b);

    int len = last_p2[b - a];
    int min_left = rmq[a][len];
    int min_right = rmq[b - (1 << len) + 1][len];

    if (level[min_left] < level[min_right])
      out << min_left << '\n';
    else
      out << min_right << '\n';
  }

  return 0;
}