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

#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
#define INF ((1 << 30) - 1)
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(v) v.begin(), v.end()

class LCA {
public:
  LCA(int n, const vector<int> edge[], int root = 0)
      : edge(edge), size(n), depth(n), heavy(n), prev(n) {
    depth[root] = 0;
    dfs_sz(root);
    n_heavy = 0;
    dfs_hld(root, n_heavy++, -1);
  }
  int query(int u, int v) const {
    while (heavy[u] != heavy[v]) {
      if (prev[u] == -1 || prev[v] != -1 && depth[prev[u]] < depth[prev[v]]) {
        v = prev[v];
      } else {
        u = prev[u];
      }
    }
    return depth[u] < depth[v] ? u : v;
  }

private:
  void dfs_sz(int u) {
    size[u] = 1;
    for (int v : edge[u]) {
      depth[v] = depth[u] + 1;
      dfs_sz(v);
      size[u] += size[v];
    }
  }
  void dfs_hld(int u, int h, int p) {
    prev[u] = p;
    heavy[u] = h;
    int ma = 0;
    for (int v : edge[u]) {
      ma = max(ma, size[v]);
    }
    for (int v : edge[u]) {
      if (ma == size[v]) {
        dfs_hld(v, h, p);
        ma = -1;
      } else {
        dfs_hld(v, n_heavy++, u);
      }
    }
  }
  const vector<int> *edge;
  vector<int> depth;
  vector<int> size;
  int n_heavy;
  vector<int> heavy, prev;
};

vector<int> edge[100000];
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    int k, v;
    cin >> k;
    for (int j = 0; j < k; j++) {
      cin >> v;
      edge[i].push_back(v);
    }
  }
  LCA lca(n, edge, 0);
  int q, u, v;
  cin >> q;
  for (int i = 0; i < q; i++) {
    cin >> u >> v;
    cout << lca.query(u, v) << endl;
  }
  return 0;
}


Error: 0

Fixed submission:

#include <algorithm>
#include <cassert>
#include <climits>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;

// verified
class LCA {
  int n;
  std::vector<int> _depth, idx;
  static int calcsize(int n) {
    int res = 1;
    while (res < n)
      res <<= 1;
    return res;
  }
  int minimum(int a, int b, int k, int l, int r) const {
    if (r <= a || b <= l)
      return _depth.size() - 1;
    if (a <= l && r <= b)
      return idx[k];
    else {
      int vl = minimum(a, b, k * 2 + 1, l, (l + r) / 2);
      int vr = minimum(a, b, k * 2 + 2, (l + r) / 2, r);
      return _depth[vl] < _depth[vr] ? vl : vr;
    }
  }
  void buildRMQ() {
    n = calcsize(_depth.size());
    idx.resize(2 * n - 1);
    for (int i = 0; i < (int)_depth.size(); i++)
      idx[n - 1 + i] = i;
    for (int i = _depth.size(); i < n; i++)
      idx[n - 1 + i] = _depth.size();
    _depth.push_back(INT_MAX);
    for (int i = n - 2; i >= 0; i--) {
      idx[i] = _depth[idx[i * 2 + 1]] < _depth[idx[i * 2 + 2]] ? idx[i * 2 + 1]
                                                               : idx[i * 2 + 2];
    }
  }

  std::vector<int> eulertour;
  std::vector<int> in;
  void dfs(const std::vector<int> edge[], int d, int u) {
    in[u] = eulertour.size();
    eulertour.push_back(u);
    _depth.push_back(d);
    for (int i = 0; i < edge[u].size(); i++) {
      dfs(edge, d + 1, edge[u][i]);
      eulertour.push_back(u);
      _depth.push_back(d);
    }
  }

public:
  LCA(const std::vector<int> edge[], int n, int root) : in(n) {
    dfs(edge, 1, root);
    eulertour.push_back(root);
    _depth.push_back(0);
    buildRMQ();
  }
  int query(int u, int v) const { // uとvの最小共通祖先
    if (u == v)
      return u;
    if (in[u] > in[v])
      std::swap(u, v);
    return eulertour[minimum(in[u], in[v], 0, 0, n)];
  }
  int depth(int u) const { // rootの深さが1
    return _depth[in[u]];
  }
};

class BIT { // binary indexed tree, Fenwick treeとも
  std::vector<int> bit;

public:
  BIT(const vector<int> &v) : bit(v.size() + 1, 0) {
    for (int i = 0; i < (int)v.size(); i++)
      add(i, v[i]);
  }
  void add(int i, int x) { // i番目にx加える
    i++;                   // BIT添え字は1?ｎだから
    while (i < (int)bit.size()) {
      bit[i] += x;
      i += i & -i;
    }
  }
  int sum(int a) const { //[0,a]の和
    a++;
    int res = 0;
    while (0 < a) {
      res += bit[a];
      a -= a & -a;
    }
    return res;
  }
  int sum(int a, int b) const { //[a,b]の合計
    return sum(b) - sum(a - 1);
  }
  void zeroclear() { bit.assign(bit.size(), 0); }
};

class HL {
  struct S {
    pair<int, int> par;
    // BIT segtree;
    vector<int> id;
    S(int a, int b, vector<int> v) : par(a, b), id(v) {}
  };
  int calc_size(int u, vector<int> edge[], vector<int> &msz) {
    int res = 1, sz = 0, idx = 0;
    for (int i = 0; i < (int)edge[u].size(); i++) {
      int s = calc_size(edge[u][i], edge, msz);
      if (sz < s) {
        sz = s;
        idx = i;
      }
      res += s;
    }
    msz[u] = idx;
    return res;
  }
  void build(int u, vector<int> edge[], int val[], vector<int> &msz,
             vector<int> &heavy) {
    int par = compressed.size(), pi = heavy.size(), s;
    // heavy.push_back(val[u]);
    heavy.push_back(u);
    ver[u] = make_pair(par, pi);
    if (edge[u].empty())
      compressed.push_back(S(-1, -1, heavy));
    else
      build(edge[u][msz[u]], edge, val, msz, heavy);
    for (int i = 0; i < (int)edge[u].size(); i++) {
      if (i == msz[u])
        continue;
      vector<int> light;
      s = compressed.size();
      build(edge[u][i], edge, val, msz, light);
      compressed[s].par = make_pair(par, pi);
    }
  }
  vector<S> compressed;
  vector<pair<int, int>> ver;
  LCA lca;

public:
  HL(vector<int> edge[], int val[], int n) : ver(n), lca(edge, n, 0) {
    vector<int> maxsz(n, -1);
    vector<int> heavy;
    calc_size(0, edge, maxsz);
    build(0, edge, val, maxsz, heavy);
  }
  long long query(int u, int v) const {
    int w = lca.query(u, v);
    pair<int, int> a, b, c;
    a = ver[u];
    b = ver[v];
    c = ver[w];
    long long res = 0;
    while (c.first != a.first) {
      // res+=compressed[a.first].segtree.sum(a.second);
      a = compressed[a.first].par;
    }
    assert(c.second <= a.second);
    // res+=compressed[c.first].segtree.sum(c.second,a.second);
    while (c.first != b.first) {
      // res+=compressed[b.first].segtree.sum(b.second);
      b = compressed[b.first].par;
    }
    assert(c.second <= b.second);
    // if(c.second+1<=b.second)res+=compressed[c.first].segtree.sum(c.second+1,b.second);
    // return res;
    return compressed[c.first].id[min(a.second, b.second)];
  }
  /*void update(int u,int val){
          pair<int,int> a=ver[u];
          int x=compressed[a.first].segtree.sum(a.second,a.second);
          compressed[a.first].segtree.add(a.second,val-x);
  }*/
};

vector<int> edge[100000];
int val[100000];
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    int k, v;
    cin >> k;
    for (int j = 0; j < k; j++) {
      cin >> v;
      edge[i].push_back(v);
    }
  }

  HL hl(edge, val, n);
  int q, u, v;
  cin >> q;
  for (int i = 0; i < q; i++) {
    cin >> u >> v;
    cout << hl.query(u, v) << endl;
  }
  return 0;
}