Problem:
Score : 600 points

Problem Statement

There is a tree with N vertices numbered 1 to N.
The i-th edge in this tree connects Vertex a_i and Vertex b_i, and the color and length of that edge are c_i and d_i, respectively.
Here the color of each edge is represented by an integer between 1 and N-1 (inclusive). The same integer corresponds to the same color, and different integers correspond to different colors.

Answer the following Q queries:

Query j (1 \leq j \leq Q): assuming that the length of every edge whose color is x_j is changed to y_j, find the distance between Vertex u_j and Vertex v_j. (The changes of the lengths of edges do not affect the subsequent queries.)

Constraints

2 \leq N \leq 10^5

1 \leq Q \leq 10^5

1 \leq a_i, b_i \leq N

1 \leq c_i \leq N-1

1 \leq d_i \leq 10^4

1 \leq x_j \leq N-1

1 \leq y_j \leq 10^4

1 \leq u_j < v_j \leq N

The given graph is a tree.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
a_1 b_1 c_1 d_1
:
a_{N-1} b_{N-1} c_{N-1} d_{N-1}
x_1 y_1 u_1 v_1
:
x_Q y_Q u_Q v_Q

Output

Print Q lines. The j-th line (1 \leq j \leq Q) should contain the answer to Query j.

Sample Input 1

5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4

Sample Output 1

130
200
60

The graph in this input is as follows:

Here the edges of Color 1 are shown as solid red lines, the edge of Color 2 is shown as a bold green line, and the edge of Color 4 is shown as a blue dashed line.

Query 1: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 4 is 100 + 30 = 130.

Query 2: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 5 is 100 + 100 = 200.

Query 3: Assuming that the length of every edge whose color is 3 is changed to 1000 (there is no such edge), the distance between Vertex 3 and Vertex 4 is 20 + 10 + 30 = 60. Note that the edges of Color 1 now have their original lengths.

Solution in C++ (GCC 9.2.1) (judge verdict: Runtime Error)

#include <bits/stdc++.h>
using namespace std;

template<typename T>
struct edge{ int to, color; T cost; };

const int MAX_N = 1e5;
vector<edge<long long int>> graph[MAX_N];

template<typename T>
struct LCA{
    vector<vector<int>> parent;// parent[v][i] = (2^i)th parent of v
    vector<int> depth;
    vector<T> cost;

    /* constructor (initialize) */
    LCA(int n, int root){
        depth.assign(n, -1);
        cost.resize(n);

        int h = 1;
        while((1<<h) < n) h += 1;
        parent.assign(n, vector<int>(h, -1));

        DFS(root, -1, 0, 0);// root (depth 0) has no parent (-1)

        // fill entries of parent[v][non-zero]
        for(int i=0; i+1<h; i++){
            for(int v=0; v<n; v++){
                if(parent[v][i] != -1) parent[v][i+1] = parent[parent[v][i]][i];// 2^(i+1) = 2^i * 2
            }
        }
    }

    // fill entries of parent[v][0] and depth[v], cost[v]
    void DFS(int v, int v_parent, int d, T c){
        depth[v] = d;
        cost[v]  = c;
        parent[v][0] = v_parent;// 2^0 = 1

        for(int i=0; i<graph[v].size(); i++){
            if(graph[v][i].to == v_parent) continue;

            int v_child = graph[v][i].to;
            DFS(v_child, v, d+1 , c+graph[v][i].cost);
        }
    }

    int ans(int u, int v){
        if(depth[u] > depth[v]) swap(u,v);// make v deeper

        // align depths
        for(int i=0; i<(int)parent.size(); i++){
            if((depth[v] - depth[u]) >> i & 1){// go up (update)
                v = parent[v][i];// v -> v'
            }
        }
        // trivial case
        if(u == v) return u;

        // binary search
        for(int i=(int)parent.size()-1; i>=0; i--){
            if(parent[u][i] != parent[v][i]){// go up (update)
                u = parent[u][i];// u -> u'
                v = parent[v][i];// v -> v'
            }
        }
        return parent[u][0];
    }
};

template<typename T>
struct query{ int id, color, factor; T new_cost; };

vector<query<long long int>> qs[MAX_N];// for each node
vector<int> num;
vector<long long int> total;
vector<long long int> ans;// for each query

void DFS(int v, int parent_v = -1){
    for(auto q : qs[v]){
        ans[q.id] += (q.new_cost * num[q.color] - total[q.color]) * q.factor;
        // u     : +1, 
        // v     : +1, 
        // (u,v) : -2
    }
    for(auto e : graph[v]){
        if(e.to == parent_v) continue;

        num[e.color] += 1;
        total[e.color] += e.cost;

        DFS(e.to, v);

        num[e.color] -= 1;
        total[e.color] -= e.cost;

    }
}

int main(){
    int n, q;
    cin >> n >> q;
    num.resize(n);
    total.resize(n);
    ans.resize(q);

    for(int i=0; i<n-1; i++){
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a -= 1;
        b -= 1;
        graph[a].push_back({b,c,d});
        graph[b].push_back({a,c,d});
    }

    LCA<long long int> lca(n, 0);
    
    for(int i=0; i<q; i++){
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        u -= 1;
        v -= 1;

        int w = lca.ans(u,v);
        ans[i] = lca.cost[u] + lca.cost[v] - 2 * lca.cost[w];
        qs[u].push_back({i,x,+1,y});
        qs[v].push_back({i,x,+1,y});
        qs[w].push_back({i,x,-2,y});
    }

    DFS(0);
    for(int i=0; i<q; i++){
        cout << ans[i] << endl;
    }
    return 0;
}