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;
using ll = long long;
#define int ll
#define all(x) x.begin(), x.end()
#define x first
#define y second
#define mp make_pair
#define mt make_tuple

const int N = 1.1e5;
const int L = 20;
const int K = 300;

struct edge {
	int to;
	int col;
	int dst;
	edge(int a, int b, int c) : to(a), col(b), dst(c) {}
};

int n;
int q;
vector<edge> g[N];
vector<int> freq;
pair<int, int> pref[K][N];
int root[N];
int tl[N];
int tr[N];
int up[L][N];
pair<int, int> *ptr;
int timer;
vector<tuple<int, int, int>> edges[N];

void prefdfs(int v, int p) {
	for (edge e : g[v]) {
		if (e.to == p) {
			continue;
		}
		ptr[e.to].x = ptr[v].x + (e.col == timer ? e.dst : 0);
		ptr[e.to].y = ptr[v].y + (e.col == timer ? 1 : 0);
		prefdfs(e.to, v);
	}
}

void subdfs(int v, int p) {
	up[0][v] = p;
	for (int i = 1; i < L; ++i) {
		up[i][v] = up[i - 1][up[i - 1][v]];
	}
	tl[v] = timer++;
	for (edge e : g[v]) {
		if (e.to == p) {
			continue;
		}
		root[e.to] = root[v] + e.dst;
		subdfs(e.to, v);
	}
	tr[v] = timer++;
}

bool anc(int v, int u) {
	return tl[v] <= tl[u] && tr[u] <= tr[v];
}

bool onpath(int e1, int e2, int v, int u) {
	if (!anc(e1, e2)) {
		swap(e1, e2);
	}
	assert(anc(e1, e2));
	return anc(e2, v) != anc(e2, u);
}

int lca(int v, int u) {
	for (int k = L - 1; k >= 0; --k) {
		if (!anc(up[k][v], u)) {
			v = up[k][v];
		}
	}
	if (!anc(v, u)) {
		v = up[0][v];
	}
	assert(anc(v, u));
	return v;
}

pair<int, int> query(int v, int u, int c) {
	int ind = (int)(lower_bound(all(freq), c) - freq.begin());
	if (ind == (int)freq.size()) {
		int x = 0;
		int y = 0;
		for (tuple<int, int, int> e : edges[c]) {
			if (onpath(get<0>(e), get<1>(e), v, u)) {
				x += get<2>(e);
				y += 1;
			}
		}
		return {x, y};
	} else {
		int l = lca(v, u);
		pair<int, int> *arr = pref[ind];
		int x = arr[v].x + arr[u].x - 2 * arr[l].x;
		int y = arr[v].y + arr[u].y - 2 * arr[l].y;
		return {x, y};
	}
}

signed main() {
#ifdef LC
	assert(freopen("input.txt", "r", stdin));
#endif
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n >> q;
	for (int a, b, c, d, i = 0; i < n - 1; ++i) {
		cin >> a >> b >> c >> d;
		--a;
		--b;
		g[a].emplace_back(b, c, d);
		g[b].emplace_back(a, c, d);
		edges[c].emplace_back(a, b, d);
	}
	vector<pair<int, int>> srt;
	for (int i = 1; i < n; ++i) {
		srt.emplace_back(edges[i].size(), i);
	}
	sort(all(srt));
	for (int i = 0; i < min(K, (int)srt.size()); ++i) {
		freq.push_back(srt[i].y);
	}
	sort(all(freq));
	srt.clear();
	for (int i = 0; i < (int)freq.size(); ++i) {
		ptr = pref[i];
		timer = freq[i];
		prefdfs(0, 0);
	}
	timer = 0;
	subdfs(0, 0);

	for (int x, y, v, u; q--; ) {
		cin >> x >> y >> v >> u;
		--v;
		--u;
		int l = lca(v, u);
		int dist = root[v] + root[u] - 2 * root[l];
		pair<int, int> upds = query(v, u, x);
		dist += upds.y * y - upds.x;
		cout << dist << "\n";
	}
	return 0;
}