Problem p02373 (C++) — buggy submission, verdict: Runtime Error

// RMQ
#include <cassert>
#include <climits>
#include <vector>
const int INF = INT_MAX;
class RangeMinimumQuery {
public:
  explicit RangeMinimumQuery(int s);
  void update(int i, int v);
  int index(int left, int right) const;
  int value(int left, int right) const;

private:
  int parent(int node) const;
  int left_child(int node) const;
  int right_child(int node) const;
  int power_of_two(int n) const;
  int query(int left, int right, int node, int node_left, int node_right) const;
  int size_, nil_, inf_;
  std::vector<int> index_, value_;
};
RangeMinimumQuery::RangeMinimumQuery(int s)
    : size_(power_of_two(s)), nil_(size_), inf_(INF),
      index_(2 * size_ - 1, nil_), value_(size_ + 1, inf_) {}
void RangeMinimumQuery::update(int i, int v) {
  int node = i + size_ - 1;
  index_.at(node) = i;
  value_.at(i) = v;
  while ((node = parent(node)) != nil_) {
    int l = value_.at(index_.at(left_child(node)));
    int r = value_.at(index_.at(right_child(node)));
    index_.at(node) = index_.at(l <= r ? left_child(node) : right_child(node));
  }
}
int RangeMinimumQuery::index(int left, int right) const {
  return query(left, right, 0, 0, size_ - 1);
}
int RangeMinimumQuery::value(int left, int right) const {
  return value_.at(query(left, right, 0, 0, size_ - 1));
}
int RangeMinimumQuery::parent(int node) const {
  return node ? (node - 1) / 2 : nil_;
}
int RangeMinimumQuery::left_child(int node) const { return 2 * node + 1; }
int RangeMinimumQuery::right_child(int node) const { return 2 * node + 2; }
int RangeMinimumQuery::power_of_two(int n) const {
  while (n & (n - 1))
    n += n & -n;
  return n;
}
int RangeMinimumQuery::query(int left, int right, int node, int node_left,
                             int node_right) const {
  assert(left <= right);
  assert(0 <= left);
  assert(right < size_);
  if (node_right < left || right < node_left)
    return nil_;
  if (left <= node_left && node_right <= right)
    return index_.at(node);
  int middle = (node_left + node_right) / 2;
  int l = query(left, right, left_child(node), node_left, middle);
  int r = query(left, right, right_child(node), middle + 1, node_right);
  return value_.at(l) <= value_.at(r) ? l : r;
}

// Graph: Adjacency list
#include <vector>
typedef std::vector<std::vector<int>> Graph;

// LCA
#include <memory>
#include <utility>
#include <vector>
class LowestCommonAncestor {
public:
  explicit LowestCommonAncestor(const Graph &g) : id_(g.size()) {
    dfs(g, 0, 0);
    RMQ_ = std::unique_ptr<RangeMinimumQuery>(
        new RangeMinimumQuery(depth_.size()));
    for (int i = 0; i < depth_.size(); ++i)
      RMQ_->update(i, depth_.at(i));
  }
  int find(int u, int v) const {
    if (id_.at(u) > id_.at(v))
      std::swap(u, v);
    return vs_.at(RMQ_->index(id_.at(u), id_.at(v)));
  }

private:
  void dfs(const Graph &g, int current, int depth) {
    id_.at(current) = vs_.size();
    vs_.push_back(current);
    depth_.push_back(depth);
    for (const auto &next : g.at(current)) {
      dfs(g, next, depth + 1);
      vs_.push_back(current);
      depth_.push_back(depth);
    }
  }
  std::vector<int> id_, vs_, depth_;
  std::unique_ptr<RangeMinimumQuery> RMQ_;
};

#include <bits/stdc++.h>
using namespace std;
int main() {
  int n;
  cin >> n;

  Graph g(n);
  for (auto &list : g) {
    int k;
    cin >> k;
    list.resize(k);
    for (auto &c : list)
      cin >> c;
  }

  LowestCommonAncestor lca(g);
  int q;
  cin >> q;
  for (int i = 0; i < q; ++i) {
    int u, v;
    cin >> u >> v;
    cout << lca.find(u, v) << endl;
  }
}

Error: 0

Fixed submission:

// LCA: Doubling
//   ?????????: O(n * log n)
//   ?????¨???: O(log n)

// ???????????????
#include <algorithm>
#include <unordered_map>
#include <vector>
// ?????????
template <typename Label> class RootedTree {
public:
  void join(const Label &u, const Label &v);
  void initialize(const Label &root);
  const Label parent(Label v, int n) const;
  const Label lca(Label u, Label v) const;

private:
  void initialize(const Label &current, const Label &previous, int depth);
  std::unordered_map<Label, std::vector<Label>> edge_;
  std::unordered_map<Label, std::vector<Label>> parent_;
  std::unordered_map<Label, int> depth_;
};
// ????????????
template <typename Label>
void RootedTree<Label>::join(const Label &u, const Label &v) {
  edge_[u].push_back(v);
  edge_[v].push_back(u);
}
// ??????v???n????????????
template <typename Label>
const Label RootedTree<Label>::parent(Label v, int n) const {
  if (!n)
    return v;
  if (__builtin_popcount(n) == 1)
    return parent_.at(v).at(__builtin_ctz(n));
  for (int i = 31 - __builtin_clz(n); 0 <= i; --i)
    if ((n >> i) & 1)
      v = parent_.at(v).at(i);
  return v;
}
// ?????????
template <typename Label>
void RootedTree<Label>::initialize(const Label &root) {
  initialize(root, root, 0);
}
template <typename Label>
void RootedTree<Label>::initialize(const Label &current, const Label &previous,
                                   int depth) {
  depth_[current] = depth;
  parent_[current].push_back(previous);
  for (int i = 1; (1 << i) <= depth; ++i)
    parent_[current].push_back(parent_[parent_[current][i - 1]][i - 1]);
  for (const auto &next : edge_[current])
    if (next != previous)
      initialize(next, current, depth + 1);
}
// LCA
template <typename Label>
const Label RootedTree<Label>::lca(Label u, Label v) const {
  // u, v???????????±????????????
  if (depth_.at(u) > depth_.at(v))
    std::swap(u, v);
  v = parent(v, depth_.at(v) - depth_.at(u));
  // LCA????±???????
  if (u == v)
    return u;
  for (int i = 31 - __builtin_clz(depth_.at(u)); 0 <= i; --i) {
    if (parent_.at(u).at(i) == parent_.at(v).at(i))
      continue;
    u = parent_.at(u).at(i);
    v = parent_.at(v).at(i);
    i = std::min(i, 31 - __builtin_clz(depth_.at(u)) + 1);
  }
  return parent_.at(u).at(0);
}

#include <bits/stdc++.h>
using namespace std;

int main() {
  int n;
  cin >> n;
  RootedTree<int> tree;
  for (int i = 0; i < n; ++i) {
    int k;
    cin >> k;
    for (int j = 0; j < k; ++j) {
      int c;
      cin >> c;
      tree.join(i, c);
    }
  }
  tree.initialize(0);
  int q;
  cin >> q;
  for (int i = 0; i < q; ++i) {
    int u, v;
    cin >> u >> v;
    cout << tree.lca(u, v) << endl;
  }
}