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

#include <algorithm>
#include <cstdio>
#include <queue>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

const int INF = 1 << 29;

const int V_MAX = 100000, LG_V_MAX = 17;

template <class T> struct edge {
  int v;
  T cost;
};

template <class cost_t> class static_tree_query_solver {
  int par[LG_V_MAX][V_MAX], dep[V_MAX];
  cost_t mini[LG_V_MAX][V_MAX];

  int lca(int u, int v) const {
    if (dep[u] > dep[v])
      swap(u, v);
    rep(i, LG_V_MAX) if ((dep[v] - dep[u]) >> i & 1) v = par[i][v];
    if (u == v)
      return u;

    for (int i = LG_V_MAX - 1; i >= 0; i--) {
      if (par[i][u] != par[i][v]) {
        u = par[i][u];
        v = par[i][v];
      }
    }
    return par[0][u];
  }

  cost_t up(int u, int t) const { // u から t 個上の頂点までの min をとる
    cost_t res = INF;
    rep(i, LG_V_MAX) if (t >> i & 1) {
      res = min(res, mini[i][u]);
      u = par[i][u];
    }
    return res;
  }

public:
  void build(int n, const vector<int> *T, const cost_t *val) {
    struct info {
      int u, pre, d;
    };
    static info S[V_MAX];
    int head = 0, tail = 0;
    S[tail++] = (info){0, -1, 0};
    while (head < tail) {
      int u = S[head].u, pre = S[head].pre, d = S[head].d;
      head++;
      par[0][u] = pre;
      dep[u] = d;
      rep(i, T[u].size()) {
        int v = T[u][i];
        if (v != pre) {
          mini[0][v] = min(val[u], val[v]);
          S[tail++] = (info){v, u, d + 1};
        }
      }
    }

    rep(i, LG_V_MAX - 1) rep(u, n) {
      par[i + 1][u] = (par[i][u] == -1 ? -1 : par[i][par[i][u]]);
      mini[i + 1][u] =
          (par[i][u] == -1 ? -1 : min(mini[i][u], mini[i][par[i][u]]));
    }
  }

  cost_t query(int u, int v) const {
    int w = lca(u, v);
    return min(up(u, dep[u] - dep[w]), up(v, dep[v] - dep[w]));
  }
};

class union_find {
  vector<int> a;

public:
  union_find(int n) : a(n, -1) {}
  int find(int x) {
    if (a[x] < 0)
      return x;
    return a[x] = find(a[x]);
  }
  void unite(int x, int y) {
    x = find(x), y = find(y);
    if (x != y) {
      a[x] += a[y];
      a[y] = x;
    }
  }
  int size(int x) { return -a[find(x)]; }
};

int main() {
  int n, m, k, q;
  scanf("%d%d%d%d", &n, &m, &k, &q);
  static vector<edge<int>> G[V_MAX];
  rep(i, m) {
    int u, v, cost;
    scanf("%d%d%d", &u, &v, &cost);
    u--;
    v--;
    G[u].push_back((edge<int>){v, cost});
    G[v].push_back((edge<int>){u, cost});
  }
  static int matsuri[V_MAX];
  rep(i, k) scanf("%d", matsuri + i), matsuri[i]--;

  // Dijkstra
  static int d[V_MAX]; // d[u] := ( 頂点 u から一番近いお祭りまでの距離 )
  {
    priority_queue<pair<int, int>> Q;
    rep(u, n) d[u] = INF;
    rep(i, k) d[matsuri[i]] = 0, Q.push(make_pair(0, matsuri[i]));
    while (!Q.empty()) {
      int d_now = -Q.top().first, u = Q.top().second;
      Q.pop();
      if (d[u] < d_now)
        continue;
      rep(i, G[u].size()) {
        int v = G[u][i].v, cost = G[u][i].cost;
        if (d[v] > d[u] + cost) {
          d[v] = d[u] + cost;
          Q.push(make_pair(-d[v], v));
        }
      }
    }
  }

  // Kruskal
  static vector<int> MST[V_MAX];
  {
    static pair<pair<int, int>, pair<int, int>> E[200000];
    int idx = 0;
    rep(u, n) rep(i, G[u].size()) {
      int v = G[u][i].v;
      if (u < v)
        E[idx++] = make_pair(make_pair(min(d[u], d[v]), max(d[u], d[v])),
                             make_pair(u, v));
    }
    sort(E, E + m);

    union_find U(n);
    for (int i = m - 1; i >= 0; i--) {
      int u = E[i].second.first, v = E[i].second.second;
      if (U.find(u) != U.find(v)) {
        U.unite(u, v);
        MST[u].push_back(v);
        MST[v].push_back(u);
      }
    }
  }

  // query
  static static_tree_query_solver<int> L;
  L.build(n, MST, d);
  while (q--) {
    int s, t;
    scanf("%d%d", &s, &t);
    s--;
    t--;
    printf("%d\\n", L.query(s, t));
  }

  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <queue>
#include <set>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

const int INF = 1 << 29;

const int V_MAX = 100000, LG_V_MAX = 17;

template <class T> struct edge {
  int v;
  T cost;
};

template <class cost_t> class static_tree_query_solver {
  int par[LG_V_MAX][V_MAX], dep[V_MAX];
  cost_t mini[LG_V_MAX][V_MAX];

  int lca(int u, int v) const {
    if (dep[u] > dep[v])
      swap(u, v);
    rep(i, LG_V_MAX) if ((dep[v] - dep[u]) >> i & 1) v = par[i][v];
    if (u == v)
      return u;

    for (int i = LG_V_MAX - 1; i >= 0; i--) {
      if (par[i][u] != par[i][v]) {
        u = par[i][u];
        v = par[i][v];
      }
    }
    return par[0][u];
  }

  cost_t up(int u, int t) const { // u から t 個上の頂点までの min をとる
    cost_t res = INF;
    rep(i, LG_V_MAX) if (t >> i & 1) {
      res = min(res, mini[i][u]);
      u = par[i][u];
    }
    return res;
  }

public:
  void build(int n, const vector<int> *T, const cost_t *val) {
    struct info {
      int u, pre, d;
    };
    static info S[V_MAX];
    int head = 0, tail = 0;
    S[tail++] = (info){0, -1, 0};
    while (head < tail) {
      int u = S[head].u, pre = S[head].pre, d = S[head].d;
      head++;
      par[0][u] = pre;
      dep[u] = d;
      rep(i, T[u].size()) {
        int v = T[u][i];
        if (v != pre) {
          mini[0][v] = min(val[u], val[v]);
          S[tail++] = (info){v, u, d + 1};
        }
      }
    }

    rep(i, LG_V_MAX - 1) rep(u, n) {
      par[i + 1][u] = (par[i][u] == -1 ? -1 : par[i][par[i][u]]);
      mini[i + 1][u] =
          (par[i][u] == -1 ? -1 : min(mini[i][u], mini[i][par[i][u]]));
    }
  }

  cost_t query(int u, int v) const {
    int w = lca(u, v);
    return min(up(u, dep[u] - dep[w]), up(v, dep[v] - dep[w]));
  }
};

int main() {
  int n, m, k, q;
  scanf("%d%d%d%d", &n, &m, &k, &q);
  static vector<edge<int>> G[V_MAX];
  rep(i, m) {
    int u, v, cost;
    scanf("%d%d%d", &u, &v, &cost);
    u--;
    v--;
    G[u].push_back((edge<int>){v, cost});
    G[v].push_back((edge<int>){u, cost});
  }
  static int matsuri[V_MAX];
  rep(i, k) scanf("%d", matsuri + i), matsuri[i]--;

  // Dijkstra
  static int d[V_MAX]; // d[u] := ( 頂点 u から一番近いお祭りまでの距離 )
  {
    priority_queue<pair<int, int>> Q;
    rep(u, n) d[u] = INF;
    rep(i, k) d[matsuri[i]] = 0, Q.push(make_pair(0, matsuri[i]));
    while (!Q.empty()) {
      int d_now = -Q.top().first, u = Q.top().second;
      Q.pop();
      if (d[u] < d_now)
        continue;
      rep(i, G[u].size()) {
        int v = G[u][i].v, cost = G[u][i].cost;
        if (d[v] > d[u] + cost) {
          d[v] = d[u] + cost;
          Q.push(make_pair(-d[v], v));
        }
      }
    }
  }

  // build spanning tree (Prim like)
  static vector<int> T[V_MAX];
  {
    set<pair<int, int>> E;
    // <<今いる頂点の重み,直前にいた頂点の重み>,<今いる頂点,直前にいた頂点>>
    priority_queue<pair<pair<int, int>, pair<int, int>>> Q;
    int d_max = *max_element(d, d + n);
    static pair<int, int> w[V_MAX];
    rep(u, n) {
      w[u] = make_pair(-INF, -INF);
      if (d[u] == d_max)
        Q.push(make_pair(make_pair(d[u], -1), make_pair(u, -1)));
    }
    while (!Q.empty()) {
      pair<int, int> a = Q.top().first;
      int u = Q.top().second.first, u0 = Q.top().second.second;
      Q.pop();

      if (w[u] > a)
        continue;
      if (u0 != -1)
        E.insert(make_pair(min(u0, u), max(u0, u)));

      rep(i, G[u].size()) {
        int v = G[u][i].v;
        pair<int, int> a_next(d[v], a.first);
        if (w[v] < a_next) {
          w[v] = a_next;
          Q.push(make_pair(a_next, make_pair(v, u)));
        }
      }
    }

    set<pair<int, int>>::iterator it;
    for (it = E.begin(); it != E.end(); ++it) {
      int u = it->first, v = it->second;
      T[u].push_back(v);
      T[v].push_back(u);
    }
  }

  // query
  static static_tree_query_solver<int> L;
  L.build(n, T, d);
  while (q--) {
    int s, t;
    scanf("%d%d", &s, &t);
    s--;
    t--;
    printf("%d\\n", L.query(s, t));
  }

  return 0;
}