Language: C++

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define rep(i, n) FOR(i, 0, n)
#define whole(x) (x).begin(),(x).end()
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end())
using P = pair<int, int>;
#define debug(var) cerr << "[" << #var << "] " << var << endl
const ll mod = 1000000007;

template<typename T> // T: type of cost
struct lca {
  int n, root, l;
  vector<vector<int>> to;
  vector<vector<T>> co;
  vector<int> dep;
  vector<T> costs;
  vector<vector<int>> par;
  lca(int n):n(n),to(n),co(n),dep(n),costs(n) {
    l = 0;
    while ((1<<l) < n) ++l;
    par = vector<vector<int>>(n+1,vector<int>(l,n));
  }
  void addEdge(int a, int b, T c=0) {
    to[a].push_back(b); co[a].push_back(c);
    to[b].push_back(a); co[b].push_back(c);
  }
  void dfs(int v, int d=0, T c=0, int p=-1) {
    if (p != -1) par[v][0] = p;
    dep[v] = d;
    costs[v] = c;
    for (int i = 0; i < to[v].size(); ++i) {
      int u = to[v][i];
      if (u == p) continue;
      dfs(u, d+1, c+co[v][i], v);
    }
  }

  void init(int _root=0) {
    root = _root;
    dfs(root);
    for (int i = 0; i < l-1; ++i) {
      for (int v = 0; v < n; ++v) {
        par[v][i+1] = par[par[v][i]][i];
      }
    }
  }
  // LCA
  int operator()(int a, int b) {
    if (dep[a] > dep[b]) swap(a,b);
    int gap = dep[b]-dep[a];
    for (int i = l-1; i >= 0; --i) {
      int len = 1<<i;
      if (gap >= len) {
        gap -= len;
        b = par[b][i];
      }
    }
    if (a == b) return a;
    for (int i = l-1; i >= 0; --i) {
      int na = par[a][i];
      int nb = par[b][i];
      if (na != nb) a = na, b = nb;
    }
    return par[a][0];
  }
  int length(int a, int b) {
    int c = lca(a,b);
    return dep[a]+dep[b]-dep[c]*2;
  }
  T dist(int a, int b) {
    int c = lca(a,b);
    return costs[a]+costs[b]-costs[c]*2;
  }
};

struct Edge{
    int to, col, dist;
    Edge(int to, int col, int dist): to(to), col(col), dist(dist) {}
};
struct Query{
    int id, col, y, coeff;
    Query(int id, int col, int y, int coeff): id(id), col(col), y(y), coeff(coeff) {}
};

const int MX = 100005;
vector<Edge> edge[MX];
vector<Query> qu[MX];
int ans[MX];
int colsum[MX];
int colnum[MX];

void dfs(int x, int p=-1) {
    for (auto q: qu[x]) {
        ans[q.id] -= colsum[q.col];
        ans[q.id] += q.coeff * q.y * colnum[q.col];
    }
    for (auto e: edge[x]) {
        if (e.to==p) continue;
        colsum[e.col] += e.dist;
        colnum[e.col]++;
        dfs(e.to, x);
        colsum[e.col] -= e.dist;
        colnum[e.col]--;
    }
}


int main(){
    int n, q;
    cin >> n >> q;
    lca<int> g(n);
    rep(i, n-1) {
        int a, b, c, d;
        a--; b--;
        g.addEdge(a, b, d);
        edge[a].emplace_back(b, c, d);
        edge[b].emplace_back(a, c, d);
    }
    g.init();
    
    rep(i, q) {
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        u--; v--;
        int w = g(u, v);
        ans[i] = g.dist(u, v);
        qu[u].emplace_back(i, x, y, 1);
        qu[v].emplace_back(i, x, y, 1);
        qu[w].emplace_back(i, x, y, -2);
    }
    dfs(0);
    
    rep(i, q) {
        cout << ans[i] << endl;
    }
    return 0;
}


Compiler output:
a.cc: In instantiation of 'T lca<T>::dist(int, int) [with T = int]':
a.cc:128:24:   required from here
  128 |         ans[i] = g.dist(u, v);
      |                  ~~~~~~^~~~~~
a.cc:73:13: error: no matching function for call to 'lca<int>::lca(int&, int&)'
   73 |     int c = lca(a,b);
      |             ^~~~~~~~
a.cc:20:3: note: candidate: 'lca<T>::lca(int) [with T = int]'
   20 |   lca(int n):n(n),to(n),co(n),dep(n),costs(n) {
      |   ^~~
a.cc:20:3: note:   candidate expects 1 argument, 2 provided
a.cc:13:8: note: candidate: 'lca<int>::lca(const lca<int>&)'
   13 | struct lca {
      |        ^~~
a.cc:13:8: note:   candidate expects 1 argument, 2 provided
a.cc:13:8: note: candidate: 'lca<int>::lca(lca<int>&&)'
a.cc:13:8: note:   candidate expects 1 argument, 2 provided