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++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
#define pb push_back
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int>pii;
const int maxn = 1e5 + 100;
const int mod = 1e9 + 7;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
int n, q, anc[maxn][17], dep[maxn], X[maxn], Y[maxn], A[maxn], B[maxn], sum[maxn], sumCol[maxn], cntCol[maxn], ans[maxn];
vector<pii>que[maxn];
vector<tuple<int, int, int> >adj[maxn];
void dfs(int v, int p)
{
    anc[v][0] = p;
    dep[v] = dep[p] + 1;
    for(int i = 1; i < 17; i++)
        anc[v][i] = anc[anc[v][i - 1]][i - 1];
    for(tuple<int, int, int>aa : adj[v])
    {
        int to, c, w;
        tie(to, c, w) = aa;
        if(to != p)
        {
            sum[to] = sum[v] + w;
            dfs(to, v);
        }
    }
}
int lca(int a, int b)
{
    if(dep[a] > dep[b])
        swap(a, b);
    for(int i = 16; i >= 0; i--)
        if(dep[anc[b][i]] >= dep[a])
            b = anc[b][i];
    if(a == b)
        return a;
    for(int i = 16; i >= 0; i--)
        if(anc[a][i] != anc[b][i])
            a = anc[a][i], b = anc[b][i];
    return anc[a][0];
}
void dfs2(int v, int p)
{
    for(pii p : que[v])
    {
        int i, d;
        tie(i, d) = p;
        ans[i] += d * cntCol[X[i]] * Y[i];
        ans[i] -= d * sumCol[X[i]];
    }
    for(tuple<int, int, int>aa :adj[v])
    {
        int to, c, w;
        tie(to, c, w) = aa;
        if(to != p)
        {
            cntCol[c]++;
            sumCol[c] += w;
            dfs2(to, v);
            cntCol[c]--;
            sumCol[c] -= w;
        }
    }
}
int main()
{
    ios_base::sync_with_stdio(false), cin.tie(0);
    cin >> n >> q;
    for(int i = 0; i < n - 1; i++)
    {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        adj[a].pb(make_tuple(b, c, d));
        adj[b].pb(make_tuple(a, c, d));
    }
    dfs(1, 0);
    for(int i = 0; i < q; i++)
    {
        int a, b;
        cin >> X[i] >> Y[i] >> a >> b;
        A[i] = a, B[i] = b;
        if(dep[a] > dep[b])
            swap(a, b);
        int LCA = lca(a, b);
        ans[i] = sum[a] + sum[b] - 2 * sum[LCA];
        if(a == LCA)
            que[a].pb({i, -1}), que[b].pb({i, +1});
        else
        {
            que[LCA].pb({i, -2});
            que[a].pb({i, +1});
            que[b].pb({i, +1});
        }
    }
    dfs2(1, 0);
    for(int i = 0; i < q; i++)
        cout << ans[i] << "\n";
    return 0;
}