Problem p02986 (C++)

Buggy submission (status: Runtime Error):
#include <iostream>
#include <map>
#include <set>
#include <vector>

using namespace std;

class Edge {
public:
  explicit Edge(int src, int dst, int color, int len)
      : src(src), dst(dst), color(color), len(len) {}
  int src, dst, color, len;
};

class Query {
public:
  explicit Query(int x, int y, int u, int v)
      : x(x), y(y), u(u), v(v), lca(-1) {}
  int x, y, u, v, lca;
};

class Solver {
public:
  explicit Solver(int N) : parents(N), depth(N), dist(N), needs(N), info(N) {}
  void makeParents(const vector<vector<Edge>> &g) { travel(g, 0, -1); }
  void readQueries(const vector<Query> &query) {
    for (auto &q : query) {
      int lca = getLCA(q.u, q.v);
      needs[q.u].insert(q.x);
      needs[q.v].insert(q.x);
      needs[lca].insert(q.x);
    }
  }
  void prepare(const vector<vector<Edge>> &g) {
    vector<pair<int, int>> colors(g.size(), make_pair(0, 0));
    prepareImpl_(g, 0, -1, 0, colors);
  }
  void solve(const vector<Query> &query) {
    for (auto &q : query) {
      int lca = getLCA(q.u, q.v);
      int d = dist[q.u] + dist[q.v] - 2 * dist[lca];
      int num = info[q.u][q.x].first + info[q.v][q.x].first -
                2 * info[lca][q.x].first;
      int pd = info[q.u][q.x].second + info[q.v][q.x].second -
               2 * info[lca][q.x].second;
      cout << (d - pd + num * q.y) << endl;
    }
  }

private:
  void travel(const vector<vector<Edge>> &g, int pos, int prev) {
    depth[pos] = (prev == -1 ? 0 : depth[prev] + 1);
    int check = prev;
    while (check != -1) {
      parents[pos].push_back(check);
      if (parents[check].size() <= parents[pos].size())
        break;
      check = parents[check][parents[pos].size() - 1];
    }
    for (auto &e : g[pos]) {
      if (e.dst == prev)
        continue;
      travel(g, e.dst, pos);
    }
  }
  void prepareImpl_(const vector<vector<Edge>> &g, int pos, int prev, int d,
                    vector<pair<int, int>> &colors) {
    dist[pos] = d;
    for (auto t : needs[pos]) {
      info[pos][t] = colors[t];
    }
    for (auto &e : g[pos]) {
      if (e.dst == prev)
        continue;
      ++colors[e.color].first;
      colors[e.color].second += e.len;
      prepareImpl_(g, e.dst, pos, d + e.len, colors);
      --colors[e.color].first;
      colors[e.color].second -= e.len;
    }
  }
  int toParents(int pos, int step) {
    for (int d = 0; step; d++) {
      if (step % 2)
        pos = parents[pos][d];
      step /= 2;
    }
    return pos;
  }
  int getLCA(int a, int b) {
    if (depth[a] > depth[b])
      swap(a, b);
    b = toParents(b, depth[b] - depth[a]);
    if (a == b)
      return a;
    for (int i = parents[a].size() - 1; i >= 0; i--) {
      if (parents[a].size() <= i)
        continue;
      if (parents[a][i] != parents[b][i]) {
        a = parents[a][i];
        b = parents[b][i];
      }
    }
    return parents[a][0];
  }

private:
  vector<vector<int>> parents;
  vector<int> depth;
  vector<int> dist;
  vector<set<int>> needs;
  vector<map<int, pair<int, int>>> info;
};

int main() {
  int N, Q;
  while (cin >> N >> Q) {
    vector<vector<Edge>> g(N);
    for (int i = 0; i < N - 1; i++) {
      int a, b, c, d;
      cin >> a >> b >> c >> d;
      --a;
      --b;
      g[a].emplace_back(a, b, c, d);
      g[b].emplace_back(b, a, c, d);
    }
    vector<Query> query;
    for (int i = 0; i < Q; i++) {
      int x, y, u, v;
      cin >> x >> y >> u >> v;
      --u;
      --v;
      query.emplace_back(x, y, u, v);
    }
    Solver solver(N);
    solver.makeParents(g);
    solver.readQueries(query);
    solver.prepare(g);
    solver.solve(query);
  }
}

Fixed submission:
#include <iostream>
#include <map>
#include <set>
#include <vector>

using namespace std;

class Edge {
public:
  explicit Edge(int src, int dst, int color, int len)
      : src(src), dst(dst), color(color), len(len) {}
  int src, dst, color, len;
};

class Query {
public:
  explicit Query(int x, int y, int u, int v)
      : x(x), y(y), u(u), v(v), lca(-1) {}
  int x, y, u, v, lca;
};

class Solver {
public:
  explicit Solver(int N) : parents(N), depth(N), dist(N), needs(N), info(N) {}
  void makeParents(const vector<vector<Edge>> &g) { travel(g, 0, -1); }
  void readQueries(const vector<Query> &query) {
    for (auto &q : query) {
      int lca = getLCA(q.u, q.v);
      needs[q.u].insert(q.x);
      needs[q.v].insert(q.x);
      needs[lca].insert(q.x);
    }
  }
  void prepare(const vector<vector<Edge>> &g) {
    vector<pair<int, int>> colors(g.size(), make_pair(0, 0));
    prepareImpl_(g, 0, -1, 0, colors);
  }
  void solve(const vector<Query> &query) {
    for (auto &q : query) {
      int lca = getLCA(q.u, q.v);
      int d = dist[q.u] + dist[q.v] - 2 * dist[lca];
      int num = info[q.u][q.x].first + info[q.v][q.x].first -
                2 * info[lca][q.x].first;
      int pd = info[q.u][q.x].second + info[q.v][q.x].second -
               2 * info[lca][q.x].second;
      cout << (d - pd + num * q.y) << endl;
    }
  }

private:
  void travel(const vector<vector<Edge>> &g, int pos, int prev) {
    depth[pos] = (prev == -1 ? 0 : depth[prev] + 1);
    int check = prev;
    while (check != -1) {
      parents[pos].push_back(check);
      if (parents[check].size() < parents[pos].size())
        break;
      check = parents[check][parents[pos].size() - 1];
    }
    for (auto &e : g[pos]) {
      if (e.dst == prev)
        continue;
      travel(g, e.dst, pos);
    }
  }
  void prepareImpl_(const vector<vector<Edge>> &g, int pos, int prev, int d,
                    vector<pair<int, int>> &colors) {
    dist[pos] = d;
    for (auto t : needs[pos]) {
      info[pos][t] = colors[t];
    }
    for (auto &e : g[pos]) {
      if (e.dst == prev)
        continue;
      ++colors[e.color].first;
      colors[e.color].second += e.len;
      prepareImpl_(g, e.dst, pos, d + e.len, colors);
      --colors[e.color].first;
      colors[e.color].second -= e.len;
    }
  }
  int toParents(int pos, int step) {
    for (int d = 0; step; d++) {
      if (step % 2)
        pos = parents[pos][d];
      step /= 2;
    }
    return pos;
  }
  int getLCA(int a, int b) {
    if (depth[a] > depth[b])
      swap(a, b);
    b = toParents(b, depth[b] - depth[a]);
    if (a == b)
      return a;
    for (int i = parents[a].size() - 1; i >= 0; i--) {
      if (parents[a].size() <= i)
        continue;
      if (parents[a][i] != parents[b][i]) {
        a = parents[a][i];
        b = parents[b][i];
      }
    }
    return parents[a][0];
  }

private:
  vector<vector<int>> parents;
  vector<int> depth;
  vector<int> dist;
  vector<set<int>> needs;
  vector<map<int, pair<int, int>>> info;
};

int main() {
  int N, Q;
  while (cin >> N >> Q) {
    vector<vector<Edge>> g(N);
    for (int i = 0; i < N - 1; i++) {
      int a, b, c, d;
      cin >> a >> b >> c >> d;
      --a;
      --b;
      g[a].emplace_back(a, b, c, d);
      g[b].emplace_back(b, a, c, d);
    }
    vector<Query> query;
    for (int i = 0; i < Q; i++) {
      int x, y, u, v;
      cin >> x >> y >> u >> v;
      --u;
      --v;
      query.emplace_back(x, y, u, v);
    }
    Solver solver(N);
    solver.makeParents(g);
    solver.readQueries(query);
    solver.prepare(g);
    solver.solve(query);
  }
}