Language: C++

#pragma GCC optimize("Ofast")
#pragma GCC target("avx")
#include <bits/stdc++.h>
using namespace std;

#define INIT std::cin.tie(0);std::ios::sync_with_stdio(false);
#define ALL(c) (c).begin(), (c).end()
#define RALL(c) (c).rbegin(), (c).rend()
#define REP(i, n) for (int i = 0; i < static_cast<int>(n); i++)
#define FOR(i, s, n) for (int i = s; i < static_cast<int>(n); i++)
#define ASC(t) [](t& x, t& y){ return x < y; }
#define DESC(t) [](t& x, t& y){ return x > y; }
#define PSORT(s,p,e) partial_sort((s), next((s), (p)), (e))
#define VIEW(v,t) for_each((v).begin(), (v).end(), [](t& a) { cout << a << " "; }); cout << endl;

#define IN(a,x,b) (a<=x && x<=b)
#define WS std::cout<<" ";
#define NL std::cout<<"\n"
#define OUT(dist) std::cout<<(dist);
template<class T> inline T CHMAX(T& x, const T y){return x=(x<y)?y:x;}
template<class T> inline T CHMIN(T& x, const T y){return x=(x>y)?y:x;}

using PII = pair<int, int>;
using PLL = pair<long long, long long>;
using LL = long long;
using ULL = unsigned long long;
template<class T> using V = vector<T>;
template<class T> using V2 = vector<vector<T>>;

template<typename T=int> struct LCA {
    const int N, LOG2N;
    const V2<T>& g; 
    int n, root;
    V2<int> parent;
    V<int> dep; // dep : 深さ color : 辺の色 dist : 距離
    LCA(int root, const V2<T>& g, int n) : root(root), g(g), N(n), LOG2N(std::log2(n)+1) {
        parent.resize(LOG2N, V<int>(N)); dep.resize(N);
        _dfs(root, -1, 0);
        for(int i = 0; i+1 < LOG2N; i++) { // doubling
            for(int v = 0; v < N; v++) {
                if(parent[i][v] < 0) parent[i+1][v] = -1;
                else parent[i+1][v] = parent[i][parent[i][v]];
            }
        }
    }
    int query(int u, int v) {
        if(v == root || u == root) return root;
        if(dep[u] > dep[v]) std::swap(u,v);
        // u, v の深さを揃える
        for(int i = 0; i < LOG2N; i++) 
            if((dep[v]-dep[u]) >> i & 1) v = parent[i][v];
        if(u == v) return u;
        // にぶたん
        for(int i = LOG2N-1; i >= 0; i--) {
            if(parent[i][u] != parent[i][v]) 
                u = parent[i][u], v = parent[i][v];
        }
        return parent[0][u];
    }
private:
    void _dfs(int v, int par, int d) {
        parent[0][v] = par; dep[v] = d; 
        for(auto to : g[v]) {
            if(to == par) continue;
            _dfs(to, v, d+1);
        }
    }
};

V2<int> g;
map<tuple<int,int>, tuple<int,int>> m, memo;
V<tuple<int,int,int,int>> q;
map<int, V<int>> qm;
V<int> dist, colordist, colorcnt;

void dfs(int v, int par, int dis, V2<int>& g) {
    if(par != -1) dist[v] = dis;
    if(qm.find(v) != qm.end()) {
        for(auto c : qm[v]) {
            memo[make_tuple(v,c)] = make_tuple(colorcnt[c], colordist[c]);
        }
    }
    for(auto to : g[v]) {
        if(to == par) continue;
        int c, d;
        tie(c,d) = m[make_tuple(v,to)];
        colorcnt[c]++;
        colordist[c] += d;
        dfs(to, v, dist[v]+d, g);
        colorcnt[c]--;
        colordist[c] -= d;
    }
}

int main(){
    INIT;
    int N, Q; cin >> N >> Q;
    g.resize(N);
    REP(i,N-1) {
        int x, y, c, d; cin >> x >> y >> c >> d;
        x--; y--; c--;
        g[x].emplace_back(y); g[y].emplace_back(x);
        m[make_tuple(x,y)] = make_tuple(c,d);
        m[make_tuple(y,x)] = make_tuple(c,d);
    }

    LCA lca(0, g, N);
    REP(i,Q) {
        int c, d, u, v; cin >> c >> d >> u >> v;
        c--; u--; v--;
        q.push_back(make_tuple(c,d,u,v));
        int x = lca.query(u,v);
        qm[x].emplace_back(c); qm[u].emplace_back(c); qm[v].emplace_back(c);
    }
    
    dist.resize(N+1); colorcnt.resize(N); colordist.resize(N);
    dfs(0,-1,0,g);

    REP(i,Q) {
        int c, d, u, v;
        tie(c,d,u,v) = q[i];
        int x = lca.query(u,v);
        int cntx, cntu, cntv, disx, disu, disv;
        tie(cntx,disx) = memo[make_tuple(x,c)];
        tie(cntu,disu) = memo[make_tuple(u,c)];
        tie(cntv,disv) = memo[make_tuple(v,c)];
        int ans = (dist[u]-dist[x]) - (disu-disx) + (dist[v]-dist[x]) - (disv-disx);
        ans += (cntu-cntx)*d + (cntv-cntx)*d;
        cout << ans; NL;
    }
}

Compiler output:
In file included from /usr/include/c++/14/string:43,
                 from /usr/include/c++/14/bitset:52,
                 from /usr/include/x86_64-linux-gnu/c++/14/bits/stdc++.h:52,
                 from a.cc:3:
/usr/include/c++/14/bits/allocator.h: In destructor 'std::_Vector_base<std::vector<int>, std::allocator<std::vector<int> > >::_Vector_impl::~_Vector_impl()':
/usr/include/c++/14/bits/allocator.h:182:7: error: inlining failed in call to 'always_inline' 'std::allocator< <template-parameter-1-1> >::~allocator() noexcept [with _Tp = std::vector<int>]': target specific option mismatch
  182 |       ~allocator() _GLIBCXX_NOTHROW { }
      |       ^
In file included from /usr/include/c++/14/vector:66,
                 from /usr/include/c++/14/functional:64,
                 from /usr/include/x86_64-linux-gnu/c++/14/bits/stdc++.h:53:
/usr/include/c++/14/bits/stl_vector.h:132:14: note: called from here
  132 |       struct _Vector_impl
      |              ^~~~~~~~~~~~