Problem p02986 (C++)

Buggy submission (status: Runtime Error):
#include "bits/stdc++.h"
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vi>;
using vvl = vector<vl>;
const ll INF = 1LL << 60;
const ll MOD = 1000000007;
template <class T> bool chmax(T &a, const T &b) {
  return (a < b) ? (a = b, 1) : 0;
}
template <class T> bool chmin(T &a, const T &b) {
  return (b < a) ? (a = b, 1) : 0;
}
template <class C> void print(const C &c, std::ostream &os = std::cout) {
  std::copy(std::begin(c), std::end(c),
            std::ostream_iterator<typename C::value_type>(os, " "));
  os << std::endl;
}

// 0-indexed bottom up Segment Tree
// UNIT is the identity element of operation func
template <typename T = int> struct SegmentTree {
  using F = function<T(T, T)>;
  int n;
  vector<T> dat;
  F func;
  T UNIT;

  SegmentTree(int n_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
    n = 1;
    // full binary tree: num of leaves = n = 2^k >= n_
    while (n < n_)
      n *= 2;
    dat.assign(2 * n - 1, UNIT);
  }
  SegmentTree(vector<T> v_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
    n = 1;
    while (n < v_.size())
      n *= 2;
    dat.assign(2 * n - 1, UNIT);
    for (int i = 0; i < v_.size(); ++i) {
      dat[n - 1 + i] = v_[i];
    }
    for (int i = n - 2; i >= 0; --i) {
      dat[i] = func(dat[2 * i + 1], dat[2 * i + 2]);
    }
  }
  void update(int k, T a) {
    // leaves are at index n-1 to 2*n-2
    k += n - 1;
    dat[k] = a;
    while (k > 0) {
      // k -> parent node
      k = (k - 1) / 2;
      // func(child nodes)
      dat[k] = func(dat[2 * k + 1], dat[2 * k + 2]);
    }
  }
  // get result of func() in [l, r)
  T query(int l, int r) {
    l += n - 1;
    r += n - 1;
    T ret = UNIT;
    while (l < r) {
      if ((l & 1) == 0)
        ret = func(ret, dat[l]);
      if ((r & 1) == 0)
        ret = func(ret, dat[r - 1]);
      l = l / 2;
      r = (r - 1) / 2;
    }
    return ret;
  }
};

// get LCA on the tree
// constructor: n = size of the graph
// addEdge:
// build: after adding all edge, build Euler tour and seg tree
struct LCA {
  int n;
  int k;
  vector<int> depth;
  vector<int> eulerTour;
  vector<int> firstVisit;
  vector<vector<int>> edges;
  SegmentTree<pair<int, int>> segTree;
  static pair<int, int> pairComp(pair<int, int> a, pair<int, int> b) {
    if (a.first < b.first)
      return a;
    else
      return b;
  }
  LCA(int n)
      : n(n), k(0), depth(2 * n - 1), eulerTour(2 * n - 1), firstVisit(n),
        edges(n),
        segTree(2 * n, pairComp, make_pair(numeric_limits<int>::max(), 0)){};
  void addEdge(int from, int to) {
    edges[from].push_back(to);
    edges[to].push_back(from);
  }
  void dfs(int curr = 0, int par = -1, int d = 0) {
    firstVisit[curr] = k;
    eulerTour[k] = curr;
    depth[k++] = d;
    for (auto &e : edges[curr]) {
      if (e != par) {
        dfs(e, curr, d + 1);
        eulerTour[k] = curr;
        depth[k++] = d;
      }
    }
  }
  void build(int root = 0) {
    dfs(root);
    for (int i = 0; i < 2 * n - 1; ++i) {
      segTree.update(i, make_pair(depth[i], eulerTour[i]));
    }
  }
  // return LCA node of l and r
  int operator()(int l, int r) {
    int left = firstVisit[l];
    int right = firstVisit[r];
    if (left > right)
      swap(left, right);
    return segTree.query(left, right + 1).second;
  }
  int getDepth(int k) { return depth[firstVisit[k]]; }
};

int main() {
  int n, q;
  cin >> n >> q;
  LCA lca(n);
  vector<vector<pair<int, pii>>> edges(n);
  for (int i = 0; i < n - 1; ++i) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    a--, b--;
    lca.addEdge(a, b);
    edges[a].push_back({b, {c, d}});
    edges[b].push_back({a, {c, d}});
  }
  lca.build();
  vl ret(q);
  struct query {
    int i, x, y, sign;
  };
  vector<vector<query>> vq(n);
  for (int i = 0; i < q; ++i) {
    int x, y, u, v;
    cin >> x >> y >> u >> v;
    u--, v--;
    int l = lca(x, y);
    vq[u].push_back({i, x, y, 1});
    vq[v].push_back({i, x, y, 1});
    vq[l].push_back({i, x, y, -2});
  }
  vl len(n, 0), cnt(n, 0);
  ll tot = 0;
  function<void(int, int)> dfs = [&](int c, int p) {
    for (auto &q : vq[c]) {
      ll cost = tot - len[q.x] + cnt[q.x] * q.y;
      ret[q.i] += cost * q.sign;
    }
    for (auto &e : edges[c]) {
      if (e.first == p)
        continue;
      tot += e.second.second;
      len[e.second.first] += e.second.second;
      cnt[e.second.first]++;
      dfs(e.first, c);
      tot -= e.second.second;
      len[e.second.first] -= e.second.second;
      cnt[e.second.first]--;
    }
  };
  dfs(0, -1);
  for (int i = 0; i < q; ++i) {
    cout << ret[i] << "\n";
  }
  return 0;
}

Fixed submission:
#include "bits/stdc++.h"
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vi>;
using vvl = vector<vl>;
const ll INF = 1LL << 60;
const ll MOD = 1000000007;
template <class T> bool chmax(T &a, const T &b) {
  return (a < b) ? (a = b, 1) : 0;
}
template <class T> bool chmin(T &a, const T &b) {
  return (b < a) ? (a = b, 1) : 0;
}
template <class C> void print(const C &c, std::ostream &os = std::cout) {
  std::copy(std::begin(c), std::end(c),
            std::ostream_iterator<typename C::value_type>(os, " "));
  os << std::endl;
}

// 0-indexed bottom up Segment Tree
// UNIT is the identity element of operation func
template <typename T = int> struct SegmentTree {
  using F = function<T(T, T)>;
  int n;
  vector<T> dat;
  F func;
  T UNIT;

  SegmentTree(int n_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
    n = 1;
    // full binary tree: num of leaves = n = 2^k >= n_
    while (n < n_)
      n *= 2;
    dat.assign(2 * n - 1, UNIT);
  }
  SegmentTree(vector<T> v_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
    n = 1;
    while (n < v_.size())
      n *= 2;
    dat.assign(2 * n - 1, UNIT);
    for (int i = 0; i < v_.size(); ++i) {
      dat[n - 1 + i] = v_[i];
    }
    for (int i = n - 2; i >= 0; --i) {
      dat[i] = func(dat[2 * i + 1], dat[2 * i + 2]);
    }
  }
  void update(int k, T a) {
    // leaves are at index n-1 to 2*n-2
    k += n - 1;
    dat[k] = a;
    while (k > 0) {
      // k -> parent node
      k = (k - 1) / 2;
      // func(child nodes)
      dat[k] = func(dat[2 * k + 1], dat[2 * k + 2]);
    }
  }
  // get result of func() in [l, r)
  T query(int l, int r) {
    l += n - 1;
    r += n - 1;
    T ret = UNIT;
    while (l < r) {
      if ((l & 1) == 0)
        ret = func(ret, dat[l]);
      if ((r & 1) == 0)
        ret = func(ret, dat[r - 1]);
      l = l / 2;
      r = (r - 1) / 2;
    }
    return ret;
  }
};

// get LCA on the tree
// constructor: n = size of the graph
// addEdge:
// build: after adding all edge, build Euler tour and seg tree
struct LCA {
  int n;
  int k;
  vector<int> depth;
  vector<int> eulerTour;
  vector<int> firstVisit;
  vector<vector<int>> edges;
  SegmentTree<pair<int, int>> segTree;
  static pair<int, int> pairComp(pair<int, int> a, pair<int, int> b) {
    if (a.first < b.first)
      return a;
    else
      return b;
  }
  LCA(int n)
      : n(n), k(0), depth(2 * n - 1), eulerTour(2 * n - 1), firstVisit(n),
        edges(n),
        segTree(2 * n, pairComp, make_pair(numeric_limits<int>::max(), 0)){};
  void addEdge(int from, int to) {
    edges[from].push_back(to);
    edges[to].push_back(from);
  }
  void dfs(int curr = 0, int par = -1, int d = 0) {
    firstVisit[curr] = k;
    eulerTour[k] = curr;
    depth[k++] = d;
    for (auto &e : edges[curr]) {
      if (e != par) {
        dfs(e, curr, d + 1);
        eulerTour[k] = curr;
        depth[k++] = d;
      }
    }
  }
  void build(int root = 0) {
    dfs(root);
    for (int i = 0; i < 2 * n - 1; ++i) {
      segTree.update(i, make_pair(depth[i], eulerTour[i]));
    }
  }
  // return LCA node of l and r
  int operator()(int l, int r) {
    int left = firstVisit[l];
    int right = firstVisit[r];
    if (left > right)
      swap(left, right);
    return segTree.query(left, right + 1).second;
  }
  int getDepth(int k) { return depth[firstVisit[k]]; }
};

int main() {
  int n, q;
  cin >> n >> q;
  LCA lca(n);
  vector<vector<pair<int, pii>>> edges(n);
  for (int i = 0; i < n - 1; ++i) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    a--, b--;
    lca.addEdge(a, b);
    edges[a].push_back({b, {c, d}});
    edges[b].push_back({a, {c, d}});
  }
  lca.build();
  vl ret(q);
  struct query {
    int i, x, y, sign;
  };
  vector<vector<query>> vq(n);
  for (int i = 0; i < q; ++i) {
    int x, y, u, v;
    cin >> x >> y >> u >> v;
    u--, v--;
    int l = lca(u, v);
    vq[u].push_back({i, x, y, 1});
    vq[v].push_back({i, x, y, 1});
    vq[l].push_back({i, x, y, -2});
  }
  vl len(n, 0), cnt(n, 0);
  ll tot = 0;
  function<void(int, int)> dfs = [&](int c, int p) {
    for (auto &q : vq[c]) {
      ll cost = tot - len[q.x] + cnt[q.x] * q.y;
      ret[q.i] += cost * q.sign;
    }
    for (auto &e : edges[c]) {
      if (e.first == p)
        continue;
      tot += e.second.second;
      len[e.second.first] += e.second.second;
      cnt[e.second.first]++;
      dfs(e.first, c);
      tot -= e.second.second;
      len[e.second.first] -= e.second.second;
      cnt[e.second.first]--;
    }
  };
  dfs(0, -1);
  for (int i = 0; i < q; ++i) {
    cout << ret[i] << "\n";
  }
  return 0;
}