Cod sursa(job #2700331)

Utilizator retrogradLucian Bicsi retrograd Data 27 ianuarie 2021 13:18:51
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.45 kb
#include <bits/stdc++.h>

using namespace std;
using Graph = vector<vector<int>>;

int lg(int n) { return 31 - __builtin_clz(n); }

struct RMQ {
  vector<vector<int>> rmq;

  RMQ(const vector<int>& v) : rmq(1 + lg(v.size()), v) {
    for (int i = 0; i + 1 < (int)rmq.size(); ++i)
      for (int j = 0; j + (2 << i) <= (int)v.size(); ++j) 
        rmq[i + 1][j] = min(rmq[i][j], rmq[i][j + (1 << i)]);
  }
  int Query(int a, int b) {
    assert(a < b); int dep = lg(b - a);
    return min(rmq[dep][a], rmq[dep][b - (1 << dep)]);
  }
};

struct LCA {
  int n, timer = 0;
  vector<int> enter, lv, lt;
  RMQ rmq;

  LCA(Graph& graph, int root = 0) :
    n(graph.size()), enter(n, -1),
    rmq((dfs(graph, root), lt)) {}

  void dfs(Graph& graph, int node) {
    enter[node] = timer++;
    for (auto vec : graph[node]) {
      if (enter[vec] != -1) continue;
      lv.push_back(node), lt.push_back(enter[node]);
      dfs(graph, vec);
    }
  }
  int Query(int a, int b) {
    if (a == b) return a;
    a = enter[a], b = enter[b];
    return lv[rmq.Query(min(a, b), max(a, b))];
  }
  // Distance is 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;
  Graph graph(n);
  for (int i = 1; i < n; ++i) {
    int p; cin >> p; graph[p - 1].push_back(i);
  }
  LCA L(graph);
  for (int i = 0; i < q; ++i) {
    int a, b; cin >> a >> b;
    cout << L.Query(a - 1, b - 1) + 1 << '\n';
  }
  return 0;
}