Problem p02986 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

const int K = 20;
const int N = 100 + 9;

struct Query {
  int v;
  int c;
  int color;
  int index;

  Query(int v_, int c_, int color_, int index_) {
    v = v_;
    c = c_;
    color = color_;
    index = index_;
  }
};

vector<tuple<int, int, int>> g[N];

int cnt[N];
int sm[N];

int cans[N];
int qcnt[N];
int qsm[N];
int qd[N];

vector<Query> q[N];

void dfs(int cur, int p) {
  for (auto qr : q[cur]) {
    qcnt[qr.index] += qr.c * cnt[qr.color];
    qsm[qr.index] += qr.c * sm[qr.color];
  }
  for (auto t : g[cur]) {
    int u, cl, w;
    tie(u, cl, w) = t;
    if (u != p) {
      cnt[cl]++;
      sm[cl] += w;
      dfs(u, cur);
      cnt[cl]--;
      sm[cl] -= w;
    }
  }
}

int alls[N];

int pr[N];
int up[K][N];
int tin[N];
int tout[N];

int timer = 0;

void jfs(int cur, int p, int len) {
  tin[cur] = timer++;
  pr[cur] = p;
  alls[cur] = len;
  for (auto t : g[cur]) {
    int u, cl, w;
    tie(u, cl, w) = t;
    if (u != p) {
      jfs(u, cur, len + w);
    }
  }
  tout[cur] = timer++;
}

void init(int n) {
  for (int i = 0; i < n; i++) {
    up[0][i] = pr[i];
  }
  for (int i = 0; i + 1 < K; i++) {
    for (int j = 0; j < n; j++) {
      int mid = up[i][j];
      if (mid == -1) {
        up[i + 1][j] = mid;
      } else {
        up[i + 1][j] = up[i][mid];
      }
    }
  }
}

int anc(int u, int v) { return tin[u] <= tin[v] && tout[v] <= tout[u]; }

int lca(int u, int v) {
  if (anc(u, v)) {
    return u;
  } else if (anc(v, u)) {
    return v;
  } else {
    for (int i = K - 1; i >= 0; i--) {
      if (up[i][u] != -1 && !anc(up[i][u], v)) {
        u = up[i][u];
      }
    }
    return pr[u];
  }
}

signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);

  int n, qc;
  cin >> n >> qc;
  for (int i = 0; i + 1 < n; i++) {
    int u, v, c, w;
    cin >> u >> v >> c >> w;
    u--, v--;
    g[u].push_back(make_tuple(v, c, w));
    g[v].push_back(make_tuple(u, c, w));
  }
  jfs(0, -1, 0);
  init(n);
  for (int i = 0; i < qc; i++) {
    int cl, nd, u, v;
    cin >> cl >> nd >> u >> v;
    u--, v--;
    q[u].push_back(Query(u, 1, cl, i));
    q[v].push_back(Query(v, 1, cl, i));
    int l = lca(u, v);
    q[l].push_back(Query(l, -2, cl, i));
    qd[i] = nd;
    cans[i] = alls[u] + alls[v] - 2 * alls[l];
  }
  dfs(0, -1);
  for (int i = 0; i < qc; i++) {
    cans[i] -= qsm[i];
    cans[i] += qcnt[i] * qd[i];
    cout << cans[i] << '\n';
  }
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

const int K = 20;
const int N = 1e5 + 9;

struct Query {
  int v;
  int c;
  int color;
  int index;

  Query(int v_, int c_, int color_, int index_) {
    v = v_;
    c = c_;
    color = color_;
    index = index_;
  }
};

vector<tuple<int, int, int>> g[N];

int cnt[N];
int sm[N];

int cans[N];
int qcnt[N];
int qsm[N];
int qd[N];

vector<Query> q[N];

void dfs(int cur, int p) {
  for (auto qr : q[cur]) {
    qcnt[qr.index] += qr.c * cnt[qr.color];
    qsm[qr.index] += qr.c * sm[qr.color];
  }
  for (auto t : g[cur]) {
    int u, cl, w;
    tie(u, cl, w) = t;
    if (u != p) {
      cnt[cl]++;
      sm[cl] += w;
      dfs(u, cur);
      cnt[cl]--;
      sm[cl] -= w;
    }
  }
}

int alls[N];

int pr[N];
int up[K][N];
int tin[N];
int tout[N];

int timer = 0;

void jfs(int cur, int p, int len) {
  tin[cur] = timer++;
  pr[cur] = p;
  alls[cur] = len;
  for (auto t : g[cur]) {
    int u, cl, w;
    tie(u, cl, w) = t;
    if (u != p) {
      jfs(u, cur, len + w);
    }
  }
  tout[cur] = timer++;
}

void init(int n) {
  for (int i = 0; i < n; i++) {
    up[0][i] = pr[i];
  }
  for (int i = 0; i + 1 < K; i++) {
    for (int j = 0; j < n; j++) {
      int mid = up[i][j];
      if (mid == -1) {
        up[i + 1][j] = mid;
      } else {
        up[i + 1][j] = up[i][mid];
      }
    }
  }
}

int anc(int u, int v) { return tin[u] <= tin[v] && tout[v] <= tout[u]; }

int lca(int u, int v) {
  if (anc(u, v)) {
    return u;
  } else if (anc(v, u)) {
    return v;
  } else {
    for (int i = K - 1; i >= 0; i--) {
      if (up[i][u] != -1 && !anc(up[i][u], v)) {
        u = up[i][u];
      }
    }
    return pr[u];
  }
}

signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);

  int n, qc;
  cin >> n >> qc;
  for (int i = 0; i + 1 < n; i++) {
    int u, v, c, w;
    cin >> u >> v >> c >> w;
    u--, v--;
    g[u].push_back(make_tuple(v, c, w));
    g[v].push_back(make_tuple(u, c, w));
  }
  jfs(0, -1, 0);
  init(n);
  for (int i = 0; i < qc; i++) {
    int cl, nd, u, v;
    cin >> cl >> nd >> u >> v;
    u--, v--;
    q[u].push_back(Query(u, 1, cl, i));
    q[v].push_back(Query(v, 1, cl, i));
    int l = lca(u, v);
    q[l].push_back(Query(l, -2, cl, i));
    qd[i] = nd;
    cans[i] = alls[u] + alls[v] - 2 * alls[l];
  }
  dfs(0, -1);
  for (int i = 0; i < qc; i++) {
    cans[i] -= qsm[i];
    cans[i] += qcnt[i] * qd[i];
    cout << cans[i] << '\n';
  }
}