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: Time Limit Exceeded)

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

#define N 100010
#define pii pair <int, int>
#define fi first
#define se second
int n, q; 
struct node {
	int u, v, w, id;
	node() {}
	node(int v, int w) : v(v), w(w) {}
	node (int u, int v, int w, int id = 0) : u(u), v(v), w(w), id(id) {}
};
vector <vector<node>> E, Q, G;  
int res[N];  

int fa[N], deep[N], dis[N], sze[N], son[N], top[N], in[N], fin[N], cnt;
void DFS(int u) {
	sze[u] = 1;
	for (auto it : G[u]) if (it.v != fa[u]) {
		int v = it.v;
		fa[v] = u;
		deep[v] = deep[u] + 1;
		dis[v] = dis[u] + it.w;
		DFS(v);
		sze[u] += sze[v];
		if (sze[u] == -1 || sze[v] > sze[son[u]]) sze[u] = v;
	}
}
void gettop(int u, int sp) {
	top[u] = sp;
	in[u] = ++cnt;
	fin[cnt] = u;
	if (!son[u]) return;
	gettop(son[u], sp);
	for (auto it : G[u]) {
		int v = it.v;
		if (v == fa[u] || v == son[u]) continue;
		gettop(v, v);
	}
}
int querylca(int u, int v) {
	while (top[u] != top[v]) {
		if (deep[top[u]] < deep[top[v]]) {
			swap(u, v);
		}
		u = fa[top[u]];
	}
	if (deep[u] < deep[v]) swap(u, v);
	return u;
}

pii add(pii x, pii y) {
	return pii(x.fi + y.fi, x.se + y.se);
}
pii sub(pii x, pii y) {
	return pii(x.fi - y.fi, x.se - y.se);
}
struct BIT {
	pii a[N];
	void init() {
		memset(a, 0, sizeof a);
	}
	void update(int x, int s, int t) {
		for (; x < N; x += x & -x) {
			a[x] = add(a[x], pii(s, t));
		}
	}
	pii query(int x) {
		pii res = pii(0, 0);
		for (; x > 0; x -= x & -x) {
			res = add(res, a[x]);
		}
		return res;
	}
	pii query(int l, int r) {
		return sub(query(r), query(l - 1));
	}
}bit;

pii query(int u, int v) {
	pii res = pii(0, 0);
	while (top[u] != top[v]) {
		if (deep[top[u]] < deep[top[v]]) swap(u, v);
		res = add(res, bit.query(in[top[u]], in[u]));
		u = fa[top[u]];	
	}
	if (u == v) return res;
	if (deep[u] > deep[v]) swap(u, v);
	return add(res, bit.query(in[son[u]], in[v]));
}

void init() {
	bit.init();
	cnt = 0; dis[1] = 0; fa[1] = 0;
	E.clear(); E.resize(n + 1);
	Q.clear(); Q.resize(n + 1);
	G.clear(); G.resize(n + 1);
	memset(son, -1, sizeof son);
	memset(res, 0, sizeof res);
}
int main() {
	while (scanf("%d%d", &n, &q) != EOF) {
		init();
		for (int i = 1, u, v, c, d; i < n; ++i) {
			scanf("%d%d%d%d", &u, &v, &c, &d);
			G[u].push_back(node(v, d));
			G[v].push_back(node(u, d));
			E[c].push_back(node(u, v, d));
		}
		for (int i = 1, c, u, v, w; i <= q; ++i) {
			scanf("%d%d%d%d", &c, &w, &u, &v);
			Q[c].push_back(node(u, v, w, i));
		}
		DFS(1); gettop(1, 1);
		for (int i = 1; i < n; ++i) {
			if (Q[i].empty()) continue;
			for (auto &it : E[i]) {
				if (fa[it.u] == it.v) swap(it.u, it.v);
				int v = it.v, w = it.w;
				bit.update(in[v], 1, w);
			}
			for (auto it : Q[i]) {
				int u = it.u, v = it.v, w = it.w, id = it.id;
				int lca = querylca(u, v); 
				pii tmp = query(u, v);
				res[id] = dis[u] + dis[v] - 2 * dis[lca] - tmp.se + w * tmp.fi;
			}
			for (auto it : E[i]) {
				bit.update(in[it.v], -1, -it.w);
			}
		}
		for (int i = 1; i <= q; ++i) printf("%d\n", res[i]);
	}
	return 0;
}