Problem p02986 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fastIO ios_base::sync_with_stdio(false), cin.tie(NULL)

struct LCA {
  vector<int> height, euler, first, logs;
  vector<bool> visited;
  vector<vector<int>> st;

  int min_height(int a, int b) {
    if (height[a] < height[b])
      return a;
    return b;
  }

  void build_sparse(int maxN) {
    st = vector<vector<int>>(maxN, vector<int>(30));
    logs = vector<int>(maxN + 1);
    logs[1] = 0;
    for (int i = 2; i <= maxN; i++) {
      logs[i] = logs[i / 2] + 1;
    }
    for (int i = 0; i < maxN; i++) {
      st[i][0] = euler[i];
    }

    for (int j = 1; j <= 30; j++) {
      for (int i = 0; i + (1 << j) <= maxN; i++) {
        st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
      }
    }
  }

  int lca(int u, int v) {
    u = first[u];
    v = first[v];
    if (u > v)
      swap(u, v);

    int lg = logs[v - u + 1];
    return min_height(st[u][lg], st[v - (1 << lg) + 1][lg]);
  }

  void dfs(vector<int> *g, int n, int depth) {
    visited[n] = 1;
    height[n] = depth;
    first[n] = euler.size();
    euler.push_back(n);
    for (auto i : g[n]) {
      if (!visited[i]) {
        dfs(g, i, depth + 1);
        euler.push_back(n);
      }
    }
  }

  LCA(vector<int> *g, int n) {
    height = vector<int>(n);
    visited = vector<bool>(n);
    first = vector<int>(n);
    dfs(g, 1, 0);
    build_sparse(euler.size());
  }
};

const int N = 1e5 + 7;
vector<int> conn[N];
vector<pair<int, pair<ll, ll>>> g[N];
pair<ll, ll> colors[N];
unordered_map<int, unordered_map<int, pair<ll, ll>>> mp;
ll dists[N];
bool visited[N];

struct query {
  int u, v, x, y;
  query(int u, int v, int x, int y) {
    this->u = u;
    this->v = v;
    this->x = x;
    this->y = y;
  }
};

void dfs(int n, int cost = 0) {
  dists[n] = cost;
  visited[n] = 1;
  for (auto c : mp[n]) {
    mp[n][c.first] = colors[c.first];
  }
  for (auto i : g[n]) {
    if (visited[i.first])
      continue;
    colors[i.second.first].first++;
    colors[i.second.first].second += i.second.second;
    dfs(i.first, cost + i.second.second);
    colors[i.second.first].first--;
    colors[i.second.first].second -= i.second.second;
  }
}

int main() {
  fastIO;
  int n;
  cin >> n;
  int q;
  cin >> q;
  for (int i = 0; i < n - 1; i++) {
    int u, v, c, d;
    cin >> u >> v >> c >> d;
    conn[u].push_back(v);
    conn[v].push_back(u);
    g[u].push_back({v, {c, d}});
    g[v].push_back({u, {c, d}});
  }
  LCA lca(conn, n + 1);

  vector<query> queries;
  while (q--) {
    int u, v, x, y;
    cin >> x >> y >> u >> v;
    mp[u][x] = {0, 0};
    mp[v][x] = {0, 0};
    mp[lca.lca(u, v)][x] = {0, 0};
    queries.push_back(query(u, v, x, y));
  }
  dfs(1, 0);
  for (auto i : queries) {
    ll dist = dists[i.u] + dists[i.v] - 2 * dists[lca.lca(i.u, i.v)];
    ll frq = mp[i.u][i.x].first + mp[i.v][i.x].first -
             2 * mp[lca.lca(i.u, i.v)][i.x].first;
    ll weight = mp[i.u][i.x].second + mp[i.v][i.x].second -
                2 * mp[lca.lca(i.u, i.v)][i.x].second;
    assert(weight <= dist);
    cout << dist - weight + frq * i.y << '\n';
  }
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fastIO ios_base::sync_with_stdio(false), cin.tie(NULL)

struct LCA {
  vector<int> height, euler, first, logs;
  vector<bool> visited;
  vector<vector<int>> st;

  int min_height(int a, int b) {
    if (height[a] < height[b])
      return a;
    return b;
  }

  void build_sparse(int maxN) {
    st = vector<vector<int>>(maxN, vector<int>(30));
    logs = vector<int>(maxN + 1);
    logs[1] = 0;
    for (int i = 2; i <= maxN; i++) {
      logs[i] = logs[i / 2] + 1;
    }
    for (int i = 0; i < maxN; i++) {
      st[i][0] = euler[i];
    }

    for (int j = 1; j <= 30; j++) {
      for (int i = 0; i + (1 << j) <= maxN; i++) {
        st[i][j] = min_height(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
      }
    }
  }

  int lca(int u, int v) {
    u = first[u];
    v = first[v];
    if (u > v)
      swap(u, v);

    int lg = logs[v - u + 1];
    return min_height(st[u][lg], st[v - (1 << lg) + 1][lg]);
  }

  void dfs(vector<int> *g, int n, int depth) {
    visited[n] = 1;
    height[n] = depth;
    first[n] = euler.size();
    euler.push_back(n);
    for (auto i : g[n]) {
      if (!visited[i]) {
        dfs(g, i, depth + 1);
        euler.push_back(n);
      }
    }
  }

  LCA(vector<int> *g, int n) {
    height = vector<int>(n);
    visited = vector<bool>(n);
    first = vector<int>(n);
    dfs(g, 1, 0);
    build_sparse(euler.size());
  }
};

const int N = 1e5 + 7;
vector<int> conn[N];
vector<pair<int, pair<ll, ll>>> g[N];
pair<ll, ll> colors[N];
unordered_map<int, unordered_map<int, pair<ll, ll>>> mp;
ll dists[N];
bool visited[N];

struct query {
  int u, v, x, y;
  query(int u, int v, int x, int y) {
    this->u = u;
    this->v = v;
    this->x = x;
    this->y = y;
  }
};

void dfs(int n, int cost = 0) {
  dists[n] = cost;
  visited[n] = 1;
  for (auto c : mp[n]) {
    mp[n][c.first] = colors[c.first];
  }
  for (auto i : g[n]) {
    if (visited[i.first])
      continue;
    colors[i.second.first].first++;
    colors[i.second.first].second += i.second.second;
    dfs(i.first, cost + i.second.second);
    colors[i.second.first].first--;
    colors[i.second.first].second -= i.second.second;
  }
}

int main() {
  fastIO;
  int n;
  cin >> n;
  int q;
  cin >> q;
  for (int i = 0; i < n - 1; i++) {
    int u, v, c, d;
    cin >> u >> v >> c >> d;
    conn[u].push_back(v);
    conn[v].push_back(u);
    g[u].push_back({v, {c, d}});
    g[v].push_back({u, {c, d}});
  }
  LCA lca(conn, n + 1);

  vector<query> queries;
  while (q--) {
    int u, v, x, y;
    cin >> x >> y >> u >> v;
    mp[u][x] = {0, 0};
    mp[v][x] = {0, 0};
    mp[lca.lca(u, v)][x] = {0, 0};
    queries.push_back(query(u, v, x, y));
  }
  dfs(1, 0);
  for (auto i : queries) {
    ll dist = dists[i.u] + dists[i.v] - 2 * dists[lca.lca(i.u, i.v)];
    ll frq = mp[i.u][i.x].first + mp[i.v][i.x].first -
             2 * mp[lca.lca(i.u, i.v)][i.x].first;
    ll weight = mp[i.u][i.x].second + mp[i.v][i.x].second -
                2 * mp[lca.lca(i.u, i.v)][i.x].second;
    assert(weight <= dist);
    cout << dist - weight + frq * i.y << '\n';
  }
}