Cod sursa(job #2691873)

Utilizator retrogradLucian Bicsi retrograd Data 30 decembrie 2020 13:33:12
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.67 kb
#include <bits/stdc++.h>

using namespace std;

template <class T>
struct RMQ {
  vector<vector<T>> rmq;

  void Build(const vector<T>& v) {
    int n = v.size(), depth = 1;
    while ((1 << depth) < n * 2) ++depth;
    rmq.assign(depth, v);
    for (int i = 0; i < depth - 1; ++i)
      for (int j = 0; j + (2 << i) <= n; ++j) 
        rmq[i + 1][j] = min(rmq[i][j], rmq[i][j + (1 << i)]);
  }
  T Query(int a, int b) {
    assert(a < b);
    int dep = 31 - __builtin_clz(b - a); // log(b - a)
    return min(rmq[dep][a], rmq[dep][b - (1 << dep)]);
  }
};

struct LCA {
  vector<int> enter, depth;
  vector<vector<int>> graph;
  vector<pair<int, int>> lin;
  RMQ<pair<int, int>> rmq;
  int timer = 0;

  LCA(int n) : enter(n, -1), depth(n), graph(n), lin(2 * n) {}

  void dfs(int node, int dep) {
    lin[timer] = {dep, node};
    enter[node] = timer++; depth[node] = dep;
    for (auto vec : graph[node])
      if (enter[vec] == -1) {
        dfs(vec, dep + 1);
        lin[timer++] = {dep, node};
      }
  }
  void AddEdge(int a, int b) {
    graph[a].push_back(b);
    graph[b].push_back(a);
  }
  void Build(int root) {
    dfs(root, 0);
    rmq.Build(lin);
  }
  int Query(int a, int b) {
    a = enter[a], b = enter[b];
    return rmq.Query(min(a, b), max(a, b) + 1).second;
  }
  int Distance(int a, int b) {
    return depth[a] + depth[b] - 2 * depth[Query(a, b)];
  }
};

int main() {
  ifstream cin("lca.in");
  ofstream cout("lca.out");

  int n, q; cin >> n >> q;
  LCA L(n);
  for (int i = 1; i < n; ++i) {
    int p; cin >> p; 
    L.AddEdge(p - 1, i);
  }
  L.Build(0);
  for (int i = 0; i < q; ++i) {
    int u, v; cin >> u >> v;
    cout << 1 + L.Query(u - 1, v - 1) << '\n';
  }
  return 0;
}