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 ff first
#define ss second
#define pb push_back
#define mp make_pair
#define ll long long
#define all(a) a.begin(),a.end()
#define endl '\n'
#define y1 y12312123

using namespace std;

const int N = 1e5 + 3;
const int inf = 1e9 + 3;
const int md = 1e9 + 7;

struct edge{
    int to;
    int col;
    int len;
    int num;
};
struct ed{
    int x, y;
    int col;
    int len;
};

struct quer{
    int x, y;
    int v, u;
    int num;
};

int n, q, x, y, col, len, h[N], dist[N], tin[N], tout[N], timer;
int pr[N][17];
vector<edge> g[N];
vector<ed> edges[N];
vector<quer> queries[N];
int d[2][N];
int anss[N];

void dfs(int v, int p = 0){
    tin[v] = ++timer;
    pr[v][0] = p;
    for(int i = 1; i < 17; ++i)pr[v][i] = pr[pr[v][i - 1]][i - 1];
    for(int i = 0; i < g[v].size(); ++i){
        int to = g[v][i].to;
        if(to == p)continue;
        int len = g[v][i].len;
        dist[to] = dist[v] + len;
        h[to] = h[v] + 1;
        dfs(to, v);
    }
    tout[v] = timer;
}

int lca(int x, int y){
    if(h[x] < h[y])swap(x, y);
    int del = h[x] - h[y];
    for(int i = 16; i >= 0; i--){
        if(del & (1 << i))x = pr[x][i];
    }
    if(x == y)return x;
    for(int i = 16; i >= 0; i--){
        if(pr[x][i] != pr[y][i]){
            x = pr[x][i];
            y = pr[y][i];
        }
    }
    return pr[x][0];
}

void update(int z, int v, int x){
    while(v < N){
        d[z][v] += x;
        v |= (v + 1);
    }
}
int get(int z, int v){
    int res = 0;
    while(v >= 0){
        res += d[z][v];
        v = (v & (v + 1)) - 1;
    }
    return res;
}

int get_dist(int v, int y){
    return dist[v] - get(1, tin[v]) + get(0, tin[v]) * y;
}

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

    cin >> n >> q;
    for(int i = 1; i < n; ++i){
        cin >> x >> y >> col >> len;
        g[x].pb({y, col, len});
        g[y].pb({x, col, len});
        edges[col].pb({x, y, col, len});
    }

    for(int i = 1; i <= q; ++i){
        int x, y, v, u;
        cin >> x >> y >> v >> u;
        queries[x].pb({x, y, v, u , i});
    }

    dfs(1);

    for(int i = 1; i < n; ++i){
        for(int j = 0; j < edges[i].size(); ++j){
            int x = edges[i][j].x;
            int y = edges[i][j].y;
            int len = edges[i][j].len;
            if(h[x] > h[y])swap(x, y);
            update(0, tin[y], 1);
            update(0, tout[y] + 1, -1);
            update(1, tin[y], len);
            update(1, tout[y] + 1, -len);
        }

        for(int j = 0; j < queries[i].size(); ++j){
            int y = queries[i][j].y;
            int v = queries[i][j].v;
            int u = queries[i][j].u;
            int lc = lca(v, u);
            anss[queries[i][j].num] = get_dist(v, y) + get_dist(u, y) - get_dist(lc, y) * 2;
        }

        for(int j = 0; j < edges[i].size(); ++j){
            int x = edges[i][j].x;
            int y = edges[i][j].y;
            int len = edges[i][j].len;
            if(h[x] > h[y])swap(x, y);
            update(0, tin[y], -1);
            update(0, tout[y] + 1, +1);
            update(1, tin[y], -len);
            update(1, tout[y] + 1, len);
        }
    }

    for(int i = 1; i <= q; ++i){
        cout << anss[i] << endl;
    }

}