Problem p02986 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#define For(i, a, b) for (int(i) = (a); (i) < (b); ++(i))
#define rFor(i, a, b) for (int(i) = (a)-1; (i) >= (b); --(i))
#define rep(i, n) For((i), 0, (n))
#define rrep(i, n) rFor((i), (n), 0)
#define fi first
#define se second
using namespace std;
typedef long long lint;
typedef pair<int, int> pii;
typedef complex<double> xy_t;
const lint mod = 1e9 + 7;
const int MAX = 100010;

typedef struct edge {
  int to, col;
  lint dist;
  edge(int t, int c, lint d) {
    to = t;
    col = c;
    dist = d;
  }
} edge;

typedef struct Segtree {
  int n = 1;
  vector<int> node;
  vector<int> depth;

  Segtree(int n_, vector<int> d) {
    while (n < n_)
      n *= 2;
    node.resize(2 * n - 1, n - 1);
    depth.resize(n, MAX);
    rep(i, d.size()) depth[i] = d[i];
  }

  void update(int i, int x) {
    i += n - 1;
    node[i] = x;
    while (i) {
      i = (i - 1) / 2;
      if (depth[node[2 * i + 1]] < depth[node[2 * i + 2]])
        node[i] = node[2 * i + 1];
      else
        node[i] = node[2 * i + 2];
    }
  }

  int getmin(int a, int b, int i, int l, int r) {
    if (r <= a || b <= l)
      return n - 1;
    if (a <= l && r <= b)
      return node[i];
    int lid = getmin(a, b, 2 * i + 1, l, (l + r) / 2);
    int rid = getmin(a, b, 2 * i + 2, (l + r) / 2, r);
    if (depth[lid] < depth[rid])
      return lid;
    else
      return rid;
  }
} Segtree;

int n, q;
int u[MAX], v[MAX], lca[MAX];
int x[MAX];
lint y[MAX];
map<pii, lint> col_num, col_dist;
lint dv[MAX];
vector<edge> G[MAX];
lint now_col[MAX], now_dist[MAX];
vector<int> used_col[MAX];

void lca_dfs(int nowv, int prev, int &cur, int dep, vector<int> &id,
             vector<int> &vs, vector<int> &depth) {
  if (id[nowv] < 0)
    id[nowv] = cur;
  vs.push_back(nowv);
  depth.push_back(dep);
  ++cur;
  for (edge &e : G[nowv])
    if (e.to != prev) {
      lca_dfs(e.to, nowv, cur, dep + 1, id, vs, depth);
      vs.push_back(nowv);
      depth.push_back(dep);
      ++cur;
    }
}

void getlca() {
  vector<int> id(n, -1);
  vector<int> vs, depth;
  int cur = 0;
  lca_dfs(0, -1, cur, 0, id, vs, depth);
  Segtree st(MAX, depth);
  rep(i, depth.size()) st.update(i, i);
  rep(i, q) {
    lca[i] = vs[st.getmin(min(id[u[i]], id[v[i]]), max(id[u[i]], id[v[i]]) + 1,
                          0, 0, st.n)];
  }
}

void dfs(int nowv, lint nowd) {
  dv[nowv] = nowd;
  for (int tc : used_col[nowv]) {
    col_num[pii(nowv, tc)] = now_col[tc];
    col_dist[pii(nowv, tc)] = now_dist[tc];
  }
  for (edge &e : G[nowv])
    if (dv[e.to] < 0) {
      ++now_col[e.col];
      now_dist[e.col] += e.dist;
      dfs(e.to, nowd + e.dist);
      --now_col[e.col];
      now_dist[e.col] -= e.dist;
    }
}

int main() {
  scanf("%d%d", &n, &q);
  rep(i, n - 1) {
    int a, b, c;
    lint d;
    scanf("%d%d%d%lld", &a, &b, &c, &d);
    G[--a].emplace_back(--b, --c, d);
    G[b].emplace_back(a, c, d);
  }
  rep(i, q) {
    scanf("%d%lld%d%d", &x[i], &y[i], &u[i], &v[i]);
    --x[i];
    --u[i];
    --v[i];
  }
  getlca();
  rep(i, q) {
    used_col[u[i]].push_back(x[i]);
    used_col[v[i]].push_back(x[i]);
    used_col[lca[i]].push_back(x[i]);
  }
  rep(i, n) {
    dv[i] = -1;
    now_col[i] = now_dist[i] = 0;
  }
  dfs(0, 0);
  rep(i, q) {
    lint d_u =
        dv[u[i]] - col_dist[pii(u[i], x[i])] + col_num[pii(u[i], x[i])] * y[i];
    lint d_v =
        dv[v[i]] - col_dist[pii(v[i], x[i])] + col_num[pii(v[i], x[i])] * y[i];
    lint d_lca = dv[lca[i]] - col_dist[pii(lca[i], x[i])] +
                 col_num[pii(lca[i], x[i])] * y[i];
    printf("%lld\n", d_u + d_v - 2 * d_lca);
  }
}

Fixed submission:
#include <bits/stdc++.h>
#define For(i, a, b) for (int(i) = (a); (i) < (b); ++(i))
#define rFor(i, a, b) for (int(i) = (a)-1; (i) >= (b); --(i))
#define rep(i, n) For((i), 0, (n))
#define rrep(i, n) rFor((i), (n), 0)
#define fi first
#define se second
using namespace std;
typedef long long lint;
typedef pair<int, int> pii;
typedef complex<double> xy_t;
const lint mod = 1e9 + 7;
const int MAX = 100010;

typedef struct edge {
  int to, col;
  lint dist;
  edge(int t, int c, lint d) {
    to = t;
    col = c;
    dist = d;
  }
} edge;

typedef struct Segtree {
  int n = 1;
  vector<int> node;
  vector<int> depth;

  Segtree(int n_, vector<int> d) {
    while (n < n_)
      n *= 2;
    node.resize(2 * n - 1, n - 1);
    depth.resize(n, MAX);
    rep(i, d.size()) depth[i] = d[i];
  }

  void update(int i, int x) {
    i += n - 1;
    node[i] = x;
    while (i) {
      i = (i - 1) / 2;
      if (depth[node[2 * i + 1]] < depth[node[2 * i + 2]])
        node[i] = node[2 * i + 1];
      else
        node[i] = node[2 * i + 2];
    }
  }

  int getmin(int a, int b, int i, int l, int r) {
    if (r <= a || b <= l)
      return n - 1;
    if (a <= l && r <= b)
      return node[i];
    int lid = getmin(a, b, 2 * i + 1, l, (l + r) / 2);
    int rid = getmin(a, b, 2 * i + 2, (l + r) / 2, r);
    if (depth[lid] < depth[rid])
      return lid;
    else
      return rid;
  }
} Segtree;

int n, q;
int u[MAX], v[MAX], lca[MAX];
int x[MAX];
lint y[MAX];
map<pii, lint> col_num, col_dist;
lint dv[MAX];
vector<edge> G[MAX];
lint now_col[MAX], now_dist[MAX];
vector<int> used_col[MAX];

void lca_dfs(int nowv, int prev, int &cur, int dep, vector<int> &id,
             vector<int> &vs, vector<int> &depth) {
  if (id[nowv] < 0)
    id[nowv] = cur;
  vs.push_back(nowv);
  depth.push_back(dep);
  ++cur;
  for (edge &e : G[nowv])
    if (e.to != prev) {
      lca_dfs(e.to, nowv, cur, dep + 1, id, vs, depth);
      vs.push_back(nowv);
      depth.push_back(dep);
      ++cur;
    }
}

void getlca() {
  vector<int> id(n, -1);
  vector<int> vs, depth;
  int cur = 0;
  lca_dfs(0, -1, cur, 0, id, vs, depth);
  Segtree st(2 * MAX, depth);
  rep(i, depth.size()) st.update(i, i);
  rep(i, q) {
    lca[i] = vs[st.getmin(min(id[u[i]], id[v[i]]), max(id[u[i]], id[v[i]]) + 1,
                          0, 0, st.n)];
  }
}

void dfs(int nowv, lint nowd) {
  dv[nowv] = nowd;
  for (int tc : used_col[nowv]) {
    col_num[pii(nowv, tc)] = now_col[tc];
    col_dist[pii(nowv, tc)] = now_dist[tc];
  }
  for (edge &e : G[nowv])
    if (dv[e.to] < 0) {
      ++now_col[e.col];
      now_dist[e.col] += e.dist;
      dfs(e.to, nowd + e.dist);
      --now_col[e.col];
      now_dist[e.col] -= e.dist;
    }
}

int main() {
  scanf("%d%d", &n, &q);
  rep(i, n - 1) {
    int a, b, c;
    lint d;
    scanf("%d%d%d%lld", &a, &b, &c, &d);
    G[--a].emplace_back(--b, --c, d);
    G[b].emplace_back(a, c, d);
  }
  rep(i, q) {
    scanf("%d%lld%d%d", &x[i], &y[i], &u[i], &v[i]);
    --x[i];
    --u[i];
    --v[i];
  }
  getlca();
  rep(i, q) {
    used_col[u[i]].push_back(x[i]);
    used_col[v[i]].push_back(x[i]);
    used_col[lca[i]].push_back(x[i]);
  }
  rep(i, n) {
    dv[i] = -1;
    now_col[i] = now_dist[i] = 0;
  }
  dfs(0, 0);
  rep(i, q) {
    lint d_u =
        dv[u[i]] - col_dist[pii(u[i], x[i])] + col_num[pii(u[i], x[i])] * y[i];
    lint d_v =
        dv[v[i]] - col_dist[pii(v[i], x[i])] + col_num[pii(v[i], x[i])] * y[i];
    lint d_lca = dv[lca[i]] - col_dist[pii(lca[i], x[i])] +
                 col_num[pii(lca[i], x[i])] * y[i];
    printf("%lld\n", d_u + d_v - 2 * d_lca);
  }
}