Language: C++

#include <bits/stdc++.h>
using namespace std;
const int SZ = 330;

struct Edge
{
  int a, b, c, d;
};

struct Query
{
  int y, u, v, id;
};

int n, q, cntColor[100100], dist[100100], depth[100100], par[100100][20], ans[100100];
int timeIn[100100], timeOut[100100], dfsTime, ds[100100];
vector <Edge> edges, coloredEdges[100100];
vector < pair<int, int> > adj[100100];
vector <Query> queries[100100];

void input()
{
  int a, b, c, d;
  cin >> n >> q;
  for (int i = 1; i < n; i++)
  {
    cin >> a >> b >> c >> d;
    edges.push_back({a, b, c, d});
    adj[a].push_back({b, d});
    adj[b].push_back({a, d});
    coloredEdges[c].push_back({a, b, c, d});
  }
}

void visit(int x)
{
  timeIn[x] = dfsTime++;
  for (auto u : adj[x])
  {
    int y = u.first, d = u.second;
    if (y != par[x][0])
    {
      dist[y] = dist[x] + d;
      depth[y] = depth[x] + 1;
      par[y][0] = x;
      visit(y);
    }
  }
  timeOut[x] = dfsTime++;
}

void initTree(int root)
{
  dfsTime = 0;
  visit(root);
  for (int j = 0; j < 17; j++)
    for (int i = 1; i <= n; i++)
      par[i][j + 1] = par[par[i][j]][j];
}

int isChild(int x, int y)
{
  return timeIn[y] <= timeIn[x] && timeOut[x] <= timeOut[y];
}

int lca(int x, int y)
{
  if (depth[x] > depth[y])
    swap(x, y);
  for (int i = 17; i >= 0; i--)
    if (depth[y] - (1 << i) >= depth[x])
      y = par[y][i];
  if (x == y)
    return x;
  for (int i = 17; i >= 0; i--)
    if (par[x][i] != par[y][i])
    {
      x = par[x][i];
      y = par[y][i];
    }
  return par[x][0];
}

void solve(int color)
{
  for (int i = 1; i <= n; i++)
  {
    dist[i] = depth[i] = par[i][0] = 0;
    ds[i] = i;
    adj[i].clear();
  }

  function<int(int)> get = [&](int x)
  {
    return x == ds[x] ? x : ds[x] = get(ds[x]);
  };

  for (auto edge : edges)
    if (edge.c != color)
    {
      int da = get(edge.a), db = get(edge.b);
      ds[da] = db;
    }

  for (auto edge : edges)
    if (edge.c == color)
    {
      int da = get(edge.a), db = get(edge.b);
      adj[da].push_back({db, edge.d});
      adj[db].push_back({da, edge.d});
    }

  initTree(get(1));
  for (auto query : queries[color])
  {
    int u = get(query.u), get(v = query.v), z = lca(u, v);
    ans[query.id] -= dist[u] + dist[v] - dist[z] * 2;
    ans[query.id] += (depth[u] + depth[v] - depth[z] * 2) * query.y;
  }
}

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

  input();
  initTree(1);

  int x, y, u, v;
  for (int i = 0; i < q; i++)
  {
    cin >> x >> y >> u >> v;
    int z = lca(u, v);
    ans[i] = dist[u] + dist[v] - dist[z] * 2;
    if (coloredEdges[x].size() >= SZ) queries[x].push_back({y, u, v, i});
    else
    {
      for (auto edge : coloredEdges[x])
      {
        int a = edge.a, b = edge.b;
        if (dist[a] > dist[b])
          swap(a, b);
        if (isChild(a, z) && (isChild(u, b) || isChild(v, b)))
          ans[i] += y - edge.d;
      }
    }
  }

  for (int i = 1; i < n; i++)
    if (!queries[i].empty())
      solve(i);

  for (int i = 0; i < q; i++)
    cout << ans[i] << '\n';
}


Compiler output:
a.cc: In function 'void solve(int)':
a.cc:116:31: error: 'v' was not declared in this scope
  116 |     int u = get(query.u), get(v = query.v), z = lca(u, v);
      |                               ^