Problem p02986 (C++)

Buggy submission (status: Runtime Error):
// need
#include <algorithm>
#include <iostream>
// data structure
#include <bitset>
#include <complex>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
// #include <deque>
#include <array>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
// etc
#include <cassert>
#include <chrono>
#include <cmath>
#include <functional>
#include <iomanip>
#include <numeric>
#include <random>

// input
#define INIT                                                                   \
  std::ios::sync_with_stdio(false);                                            \
  std::cin.tie(0);
#define VAR(type, ...)                                                         \
  type __VA_ARGS__;                                                            \
  MACRO_VAR_Scan(__VA_ARGS__);
template <typename T> void MACRO_VAR_Scan(T &t) { std::cin >> t; }
template <typename First, typename... Rest>
void MACRO_VAR_Scan(First &first, Rest &...rest) {
  std::cin >> first;
  MACRO_VAR_Scan(rest...);
}
#define VEC_ROW(type, n, ...)                                                  \
  std::vector<type> __VA_ARGS__;                                               \
  MACRO_VEC_ROW_Init(n, __VA_ARGS__);                                          \
  for (int w_ = 0; w_ < n; ++w_) {                                             \
    MACRO_VEC_ROW_Scan(w_, __VA_ARGS__);                                       \
  }
template <typename T> void MACRO_VEC_ROW_Init(int n, T &t) { t.resize(n); }
template <typename First, typename... Rest>
void MACRO_VEC_ROW_Init(int n, First &first, Rest &...rest) {
  first.resize(n);
  MACRO_VEC_ROW_Init(n, rest...);
}
template <typename T> void MACRO_VEC_ROW_Scan(int p, T &t) { std::cin >> t[p]; }
template <typename First, typename... Rest>
void MACRO_VEC_ROW_Scan(int p, First &first, Rest &...rest) {
  std::cin >> first[p];
  MACRO_VEC_ROW_Scan(p, rest...);
}
#define VEC(type, c, n)                                                        \
  std::vector<type> c(n);                                                      \
  for (auto &i : c)                                                            \
    std::cin >> i;
#define MAT(type, c, m, n)                                                     \
  std::vector<std::vector<type>> c(m, std::vector<type>(n));                   \
  for (auto &R : c)                                                            \
    for (auto &w : R)                                                          \
      std::cin >> w;
// output
#define OUT(dist) std::cout << (dist);
#define FOUT(n, dist) std::cout << std::fixed << std::setprecision(n) << (dist);
#define SOUT(n, c, dist) std::cout << std::setw(n) << std::setfill(c) << (dist);
#define SP std::cout << " ";
#define TAB std::cout << "\t";
#define BR std::cout << "\n";
#define SPBR(w, n) std::cout << (w + 1 == n ? '\n' : ' ');
#define ENDL std::cout << std::endl;
#define FLUSH std::cout << std::flush;
#define SHOW(dist)                                                             \
  { std::cerr << #dist << "\t:" << (dist) << "\n"; }
#define SHOWVECTOR(v)                                                          \
  {                                                                            \
    std::cerr << #v << "\t:";                                                  \
    for (const auto &xxx : v) {                                                \
      std::cerr << xxx << " ";                                                 \
    }                                                                          \
    std::cerr << "\n";                                                         \
  }
#define SHOWVECTOR2(v)                                                         \
  {                                                                            \
    std::cerr << #v << "\t:\n";                                                \
    for (const auto &xxx : v) {                                                \
      for (const auto &yyy : xxx) {                                            \
        std::cerr << yyy << " ";                                               \
      }                                                                        \
      std::cerr << "\n";                                                       \
    }                                                                          \
  }
#define SHOWQUEUE(a)                                                           \
  {                                                                            \
    auto tmp(a);                                                               \
    std::cerr << #a << "\t:";                                                  \
    while (!tmp.empty()) {                                                     \
      std::cerr << tmp.front() << " ";                                         \
      tmp.pop();                                                               \
    }                                                                          \
    std::cerr << "\n";                                                         \
  }
#define SHOWSTACK(a)                                                           \
  {                                                                            \
    auto tmp(a);                                                               \
    std::cerr << #a << "\t:";                                                  \
    while (!tmp.empty()) {                                                     \
      std::cerr << tmp.top() << " ";                                           \
      tmp.pop();                                                               \
    }                                                                          \
    std::cerr << "\n";                                                         \
  }
// utility
#define ALL(a) (a).begin(), (a).end()
#define FOR(w, a, n) for (int w = (a); w < (n); ++w)
#define RFOR(w, a, n) for (int w = (n)-1; w >= (a); --w)
#define REP(w, n) for (int w = 0; w < int(n); ++w)
#define RREP(w, n) for (int w = int(n) - 1; w >= 0; --w)
#define IN(a, x, b) (a <= x && x < b)
template <class T> inline T CHMAX(T &a, const T b) {
  return a = (a < b) ? b : a;
}
template <class T> inline T CHMIN(T &a, const T b) {
  return a = (a > b) ? b : a;
}
// test
template <class T> using V = std::vector<T>;
template <class T> using VV = V<V<T>>;

template <typename S, typename T>
std::ostream &operator<<(std::ostream &os, std::pair<S, T> p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}

#define random_shuffle "USE std::shuffle!";

// type/const
// #define int ll
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using PAIR = std::pair<int, int>;
using PAIRLL = std::pair<ll, ll>;
constexpr int INFINT = (1 << 30) - 1;                   // 1.07x10^ 9
constexpr int INFINT_LIM = (1LL << 31) - 1;             // 2.15x10^ 9
constexpr ll INFLL = 1LL << 60;                         // 1.15x10^18
constexpr ll INFLL_LIM = (1LL << 62) - 1 + (1LL << 62); // 9.22x10^18
constexpr double EPS = 1e-10;
constexpr int MOD = 1000000007;
constexpr double PI = 3.141592653589793238462643383279;
template <class T, size_t N> void FILL(T (&a)[N], const T &val) {
  for (auto &x : a)
    x = val;
}
template <class ARY, size_t N, size_t M, class T>
void FILL(ARY (&a)[N][M], const T &val) {
  for (auto &b : a)
    FILL(b, val);
}
template <class T> void FILL(std::vector<T> &a, const T &val) {
  for (auto &x : a)
    x = val;
}
template <class ARY, class T>
void FILL(std::vector<std::vector<ARY>> &a, const T &val) {
  for (auto &b : a)
    FILL(b, val);
}
// ------------>8------------------------------------->8------------

struct Edge {
  int from, to, cost, color;
};
struct EulerTour {
  std::vector<int> eulerTour, begin, end;
  int n, k;

  // 頂点vを根とする木gのオイラーツアー
  EulerTour(const std::vector<std::vector<Edge>> &g, int v)
      : n(g.size()), k(0) {
    begin.resize(n, 0);
    end.resize(n, 0);
    createEulerTour(g, v, -1);
  }

  // 頂点vを根とする木gのオイラーツアーを構成する
  void createEulerTour(const std::vector<std::vector<Edge>> &g, int v,
                       int par) {
    begin[v] = k++;
    eulerTour.emplace_back(v);
    for (auto e : g[v]) {
      if (e.to == par)
        continue;
      createEulerTour(g, e.to, v);
      eulerTour.emplace_back(v);
      k++;
    }
    end[v] = k;
  }
};

template <class T> class SparseTable {
  size_t N;
  std::vector<T> a;
  std::vector<size_t> logTable;
  std::vector<std::vector<T>> table;

public:
  SparseTable(const std::vector<T> &_a) : N(_a.size()), a(_a) {
    logTable.resize(N + 1, 0);
    for (size_t i = 2; i <= N; ++i) {
      logTable[i] = logTable[i >> 1] + 1;
    }

    table.resize(logTable[N] + 1, std::vector<T>(N));
    for (size_t i = 0; i < N; ++i)
      table[0][i] = a[i];
    for (size_t k = 1; k <= logTable[N]; ++k) {
      for (size_t i = 0; i + (1 << k) <= N; ++i) {
        table[k][i] =
            std::min(table[k - 1][i], table[k - 1][i + (1 << (k - 1))]);
      }
    }
  }
  // query in [l, r)
  inline T query(int l, int r) {
    int lg = logTable[r - l];
    return std::min(table[lg][l], table[lg][r - (1 << lg)]);
  }
};

constexpr int B = 333;

signed main() {
  INIT;

  VAR(int, n, Q);
  VEC_ROW(int, n - 1, a, b, c, d);
  VEC_ROW(int, Q, x, y, u, v);
  REP(i, Q)-- x[i], --u[i], --v[i];

  std::vector<std::vector<Edge>> g(n);
  REP(i, n - 1) {
    --a[i];
    --b[i];
    --c[i];
    g[a[i]].emplace_back(Edge{a[i], b[i], d[i], c[i]});
    g[b[i]].emplace_back(Edge{b[i], a[i], d[i], c[i]});
  }

  std::vector<int> depth(n, 0), dist(n, 0);
  std::vector<Edge> par(n);
  {
    auto rec = [&](auto &&f, int v, int para) -> void {
      for (auto &e : g[v])
        if (e.to != para) {
          depth[e.to] = depth[v] + 1;
          dist[e.to] = dist[v] + e.cost;
          par[e.to] = e;
          f(f, e.to, v);
        }
    };
    rec(rec, 0, -1);
  }

  EulerTour et(g, 0);
  std::vector<PAIR> for_sparse_table(et.eulerTour.size());
  REP(i, et.eulerTour.size()) {
    int v = et.eulerTour[i];
    for_sparse_table[i] = PAIR(depth[v], v);
  }
  SparseTable<PAIR> st(for_sparse_table);

  VV<int> sum(n), cnt(n);
  {
    auto rec = [&](auto &&f, int v, int par, std::vector<int> &tsum,
                   std::vector<int> &tcnt) -> void {
      if (depth[v] % B == 0) {
        sum[v] = tsum;
        cnt[v] = tcnt;
      }

      for (auto &e : g[v])
        if (e.to != par) {
          tsum[e.color] += e.cost;
          ++tcnt[e.color];
          f(f, e.to, v, tsum, tcnt);
          tsum[e.color] -= e.cost;
          --tcnt[e.color];
        }
    };
    V<int> tsum(n, 0), tcnt(n, 0);
    rec(rec, 0, -1, tsum, tcnt);
  }

  REP(i, Q) {
    PAIR lcap;
    {
      int l = et.begin[u[i]], r = et.begin[v[i]];
      if (l > r)
        std::swap(l, r);

      lcap = st.query(l, r);
    }
    int lca = lcap.second;

    int ans = 0;
    while (u[i] != lca && dist[u[i]] % B != 0) {
      auto e = par[u[i]];
      if (e.color == x[i])
        ans += y[i];
      else
        ans += e.cost;
      u[i] = e.from;
    }
    while (v[i] != lca && dist[v[i]] % B != 0) {
      auto e = par[v[i]];
      if (e.color == x[i])
        ans += y[i];
      else
        ans += e.cost;
      v[i] = e.from;
    }
    ans += depth[u[i]] + depth[v[i]] - 2 * depth[lca];
    ans -= sum[u[i]][x[i]] + sum[v[i]][x[i]] - 2 * sum[lca][x[i]];
    ans += y[i] * (cnt[u[i]][x[i]] + cnt[v[i]][x[i]] - 2 * cnt[lca][x[i]]);
    OUT(ans) BR;
  }

  return 0;
}

Fixed submission:
// need
#include <algorithm>
#include <iostream>
// data structure
#include <bitset>
#include <complex>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
// #include <deque>
#include <array>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
// etc
#include <cassert>
#include <chrono>
#include <cmath>
#include <functional>
#include <iomanip>
#include <numeric>
#include <random>

// input
#define INIT                                                                   \
  std::ios::sync_with_stdio(false);                                            \
  std::cin.tie(0);
#define VAR(type, ...)                                                         \
  type __VA_ARGS__;                                                            \
  MACRO_VAR_Scan(__VA_ARGS__);
template <typename T> void MACRO_VAR_Scan(T &t) { std::cin >> t; }
template <typename First, typename... Rest>
void MACRO_VAR_Scan(First &first, Rest &...rest) {
  std::cin >> first;
  MACRO_VAR_Scan(rest...);
}
#define VEC_ROW(type, n, ...)                                                  \
  std::vector<type> __VA_ARGS__;                                               \
  MACRO_VEC_ROW_Init(n, __VA_ARGS__);                                          \
  for (int w_ = 0; w_ < n; ++w_) {                                             \
    MACRO_VEC_ROW_Scan(w_, __VA_ARGS__);                                       \
  }
template <typename T> void MACRO_VEC_ROW_Init(int n, T &t) { t.resize(n); }
template <typename First, typename... Rest>
void MACRO_VEC_ROW_Init(int n, First &first, Rest &...rest) {
  first.resize(n);
  MACRO_VEC_ROW_Init(n, rest...);
}
template <typename T> void MACRO_VEC_ROW_Scan(int p, T &t) { std::cin >> t[p]; }
template <typename First, typename... Rest>
void MACRO_VEC_ROW_Scan(int p, First &first, Rest &...rest) {
  std::cin >> first[p];
  MACRO_VEC_ROW_Scan(p, rest...);
}
#define VEC(type, c, n)                                                        \
  std::vector<type> c(n);                                                      \
  for (auto &i : c)                                                            \
    std::cin >> i;
#define MAT(type, c, m, n)                                                     \
  std::vector<std::vector<type>> c(m, std::vector<type>(n));                   \
  for (auto &R : c)                                                            \
    for (auto &w : R)                                                          \
      std::cin >> w;
// output
#define OUT(dist) std::cout << (dist);
#define FOUT(n, dist) std::cout << std::fixed << std::setprecision(n) << (dist);
#define SOUT(n, c, dist) std::cout << std::setw(n) << std::setfill(c) << (dist);
#define SP std::cout << " ";
#define TAB std::cout << "\t";
#define BR std::cout << "\n";
#define SPBR(w, n) std::cout << (w + 1 == n ? '\n' : ' ');
#define ENDL std::cout << std::endl;
#define FLUSH std::cout << std::flush;
#define SHOW(dist)                                                             \
  { std::cerr << #dist << "\t:" << (dist) << "\n"; }
#define SHOWVECTOR(v)                                                          \
  {                                                                            \
    std::cerr << #v << "\t:";                                                  \
    for (const auto &xxx : v) {                                                \
      std::cerr << xxx << " ";                                                 \
    }                                                                          \
    std::cerr << "\n";                                                         \
  }
#define SHOWVECTOR2(v)                                                         \
  {                                                                            \
    std::cerr << #v << "\t:\n";                                                \
    for (const auto &xxx : v) {                                                \
      for (const auto &yyy : xxx) {                                            \
        std::cerr << yyy << " ";                                               \
      }                                                                        \
      std::cerr << "\n";                                                       \
    }                                                                          \
  }
#define SHOWQUEUE(a)                                                           \
  {                                                                            \
    auto tmp(a);                                                               \
    std::cerr << #a << "\t:";                                                  \
    while (!tmp.empty()) {                                                     \
      std::cerr << tmp.front() << " ";                                         \
      tmp.pop();                                                               \
    }                                                                          \
    std::cerr << "\n";                                                         \
  }
#define SHOWSTACK(a)                                                           \
  {                                                                            \
    auto tmp(a);                                                               \
    std::cerr << #a << "\t:";                                                  \
    while (!tmp.empty()) {                                                     \
      std::cerr << tmp.top() << " ";                                           \
      tmp.pop();                                                               \
    }                                                                          \
    std::cerr << "\n";                                                         \
  }
// utility
#define ALL(a) (a).begin(), (a).end()
#define FOR(w, a, n) for (int w = (a); w < (n); ++w)
#define RFOR(w, a, n) for (int w = (n)-1; w >= (a); --w)
#define REP(w, n) for (int w = 0; w < int(n); ++w)
#define RREP(w, n) for (int w = int(n) - 1; w >= 0; --w)
#define IN(a, x, b) (a <= x && x < b)
template <class T> inline T CHMAX(T &a, const T b) {
  return a = (a < b) ? b : a;
}
template <class T> inline T CHMIN(T &a, const T b) {
  return a = (a > b) ? b : a;
}
// test
template <class T> using V = std::vector<T>;
template <class T> using VV = V<V<T>>;

template <typename S, typename T>
std::ostream &operator<<(std::ostream &os, std::pair<S, T> p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}

#define random_shuffle "USE std::shuffle!";

// type/const
// #define int ll
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using PAIR = std::pair<int, int>;
using PAIRLL = std::pair<ll, ll>;
constexpr int INFINT = (1 << 30) - 1;                   // 1.07x10^ 9
constexpr int INFINT_LIM = (1LL << 31) - 1;             // 2.15x10^ 9
constexpr ll INFLL = 1LL << 60;                         // 1.15x10^18
constexpr ll INFLL_LIM = (1LL << 62) - 1 + (1LL << 62); // 9.22x10^18
constexpr double EPS = 1e-10;
constexpr int MOD = 1000000007;
constexpr double PI = 3.141592653589793238462643383279;
template <class T, size_t N> void FILL(T (&a)[N], const T &val) {
  for (auto &x : a)
    x = val;
}
template <class ARY, size_t N, size_t M, class T>
void FILL(ARY (&a)[N][M], const T &val) {
  for (auto &b : a)
    FILL(b, val);
}
template <class T> void FILL(std::vector<T> &a, const T &val) {
  for (auto &x : a)
    x = val;
}
template <class ARY, class T>
void FILL(std::vector<std::vector<ARY>> &a, const T &val) {
  for (auto &b : a)
    FILL(b, val);
}
// ------------>8------------------------------------->8------------

struct Edge {
  int from, to, cost, color;
};
struct EulerTour {
  std::vector<int> eulerTour, begin, end;
  int n, k;

  // 頂点vを根とする木gのオイラーツアー
  EulerTour(const std::vector<std::vector<Edge>> &g, int v)
      : n(g.size()), k(0) {
    begin.resize(n, 0);
    end.resize(n, 0);
    createEulerTour(g, v, -1);
  }

  // 頂点vを根とする木gのオイラーツアーを構成する
  void createEulerTour(const std::vector<std::vector<Edge>> &g, int v,
                       int par) {
    begin[v] = k++;
    eulerTour.emplace_back(v);
    for (auto e : g[v]) {
      if (e.to == par)
        continue;
      createEulerTour(g, e.to, v);
      eulerTour.emplace_back(v);
      k++;
    }
    end[v] = k;
  }
};

template <class T> class SparseTable {
  size_t N;
  std::vector<T> a;
  std::vector<size_t> logTable;
  std::vector<std::vector<T>> table;

public:
  SparseTable(const std::vector<T> &_a) : N(_a.size()), a(_a) {
    logTable.resize(N + 1, 0);
    for (size_t i = 2; i <= N; ++i) {
      logTable[i] = logTable[i >> 1] + 1;
    }

    table.resize(logTable[N] + 1, std::vector<T>(N));
    for (size_t i = 0; i < N; ++i)
      table[0][i] = a[i];
    for (size_t k = 1; k <= logTable[N]; ++k) {
      for (size_t i = 0; i + (1 << k) <= N; ++i) {
        table[k][i] =
            std::min(table[k - 1][i], table[k - 1][i + (1 << (k - 1))]);
      }
    }
  }
  // query in [l, r)
  inline T query(int l, int r) {
    int lg = logTable[r - l];
    return std::min(table[lg][l], table[lg][r - (1 << lg)]);
  }
};

constexpr int B = 333;

signed main() {
  INIT;

  VAR(int, n, Q);
  VEC_ROW(int, n - 1, a, b, c, d);
  VEC_ROW(int, Q, x, y, u, v);
  REP(i, Q)-- x[i], --u[i], --v[i];

  std::vector<std::vector<Edge>> g(n);
  REP(i, n - 1) {
    --a[i];
    --b[i];
    --c[i];
    g[a[i]].emplace_back(Edge{a[i], b[i], d[i], c[i]});
    g[b[i]].emplace_back(Edge{b[i], a[i], d[i], c[i]});
  }

  std::vector<int> depth(n, 0), dist(n, 0);
  std::vector<Edge> par(n);
  {
    auto rec = [&](auto &&f, int v, int para) -> void {
      for (auto &e : g[v])
        if (e.to != para) {
          depth[e.to] = depth[v] + 1;
          dist[e.to] = dist[v] + e.cost;
          par[e.to] = e;
          f(f, e.to, v);
        }
    };
    rec(rec, 0, -1);
  }

  EulerTour et(g, 0);
  std::vector<PAIR> for_sparse_table(et.eulerTour.size());
  REP(i, et.eulerTour.size()) {
    int v = et.eulerTour[i];
    for_sparse_table[i] = PAIR(depth[v], v);
  }
  SparseTable<PAIR> st(for_sparse_table);

  VV<int> sum(n), cnt(n);
  {
    auto rec = [&](auto &&f, int v, int par, std::vector<int> &tsum,
                   std::vector<int> &tcnt) -> void {
      if (depth[v] % B == 0) {
        sum[v] = tsum;
        cnt[v] = tcnt;
      }

      for (auto &e : g[v])
        if (e.to != par) {
          tsum[e.color] += e.cost;
          ++tcnt[e.color];
          f(f, e.to, v, tsum, tcnt);
          tsum[e.color] -= e.cost;
          --tcnt[e.color];
        }
    };
    V<int> tsum(n, 0), tcnt(n, 0);
    rec(rec, 0, -1, tsum, tcnt);
  }

  REP(i, Q) {
    PAIR lcap;
    {
      int l = et.begin[u[i]], r = et.begin[v[i]];
      if (l > r)
        std::swap(l, r);

      lcap = st.query(l, r);
    }
    int lca = lcap.second;

    auto calc = [&](int p) {
      int res = 0;
      while (depth[p] % B != 0) {
        auto e = par[p];
        if (e.color == x[i])
          res += y[i];
        else
          res += e.cost;
        p = e.from;
      }
      res += dist[p];
      res -= sum[p][x[i]];
      res += cnt[p][x[i]] * y[i];
      return res;
    };

    int ans = calc(u[i]) + calc(v[i]) - 2 * calc(lca);
    OUT(ans) BR;
  }

  return 0;
}