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 "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"

using namespace std;

//const long long int MOD = 1000000007;
const int MOD = 1000000007;
//const int MOD = 998244353;
//const long long int MOD = 998244353;
const double EPS = 1e-8;
const int MAX = 400;

int N, M, K, H, W, L, R;
//long long int N, M, K, H, W, L, R;

struct Edge {
	int to, color, cost;
	Edge(int c, int e, int f) {
		to = c, color = e, cost = f;
	}
};


class Lowest_Common_Ancestor {
	vector<vector<int>>parent;
	vector<vector<int>>edge;
	int height = 0;
	int node;
public:
	vector<int>depth;
	Lowest_Common_Ancestor(int num) {
		num++;
		node = num;
		while (num) {
			height++;
			num /= 2;
		}
		parent.resize(height);
		edge.resize(node);
		depth.resize(node);
		for (int i = 0; i < height; i++)parent[i].resize(node);
	}
	void Add_Edge(int a, int b) {
		edge[a].push_back(b);
		edge[b].push_back(a);
		return;
	}
	void Update(int rtnode) {
		queue<int>QQ;
		for (int i = 0; i < node; i++) depth[i] = INT_MAX;
		depth[rtnode] = 0;
		QQ.push(rtnode);
		while (!QQ.empty()) {
			int c = QQ.front();
			for (auto i : edge[c]) {
				if (depth[i] > depth[c] + 1) {
					depth[i] = depth[c] + 1;
					QQ.push(i);
				}
			}
			QQ.pop();
		}
		parent[0][rtnode] = -1;
		for (int i = 1; i < node; i++) {
			for (auto j : edge[i]) {
				if (depth[i] - 1 == depth[j]) {
					parent[0][i] = j;
					break;
				}
			}
		}
		for (int i = 0; i < height - 1; i++) {
			for (int j = 0; j < node; j++) {
				if (parent[i][j] < 0)parent[i + 1][j] = -1;
				else parent[i + 1][j] = parent[i][parent[i][j]];
			}
		}
		return;
	}
	inline int LCA(int u, int v) {
		if (depth[u] > depth[v])swap(u, v);
		for (int i = 0; i < height; i++) {
			if ((depth[v] - depth[u]) >> i & 1) {
				v = parent[i][v];
				if (depth[v] == depth[u])break;
			}
		}
		if (u == v)return u;
		for (int i = height - 1; i >= 0; i--) {
			if (parent[i][v] != parent[i][u]) {
				u = parent[i][u];
				v = parent[i][v];
			}
		}
		return parent[0][u];
	}
	int Dist(int u, int v) {
		return depth[u] + depth[v] - depth[LCA(u, v)] * 2;
	}
};

struct CEdge {
	int from, to, color, cost;
	CEdge(int a, int b, int c, int d) {
		from = a, to = b, color = c, cost = d;
	}
};

struct Query {
	int color, cost, l, r;
	Query(int a, int b, int c, int d) {
		color = a, cost = b, l = c, r = d;
	}
};

int num[MAX][100000];
int dis[MAX][100000];
int converter[100000];
int all_dis[100000];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> N >> K;
	for (int i = 0; i < N; i++)converter[i] = -1;
	vector<pair<int, int>>e_num(N - 1);
	vector<vector<Edge>>edge(N);
	vector<vector<CEdge>>cedge(N);
	Lowest_Common_Ancestor lca(N);
	for (int i = 1; i < N; i++) {
		cin >> L >> R >> H >> W;
		L--, R--, H--;
		lca.Add_Edge(L, R);
		e_num[H].first++;
		edge[L].push_back(Edge(R, H, W));
		edge[R].push_back(Edge(L, H, W));
	}
	vector<Query>q;
	vector<int>qnum(N);
	while (K--) {
		cin >> H >> W >> L >> R;
		qnum[H - 1]++;
		q.push_back(Query(H, W, L, R));
	}
	lca.Update(0);
	for (int i = 0; i < N; i++) {
		for (auto j : edge[i]) {
			if (lca.depth[i] < lca.depth[j.to]) {
				cedge[j.color].push_back(CEdge(i, j.to, j.color, j.cost));
			}
		}
	}
	for (int i = 0; i < N; i++) {
		e_num[i].second = i;
		e_num[i].first *= qnum[i];
	}
	sort(e_num.begin(), e_num.end());
	reverse(e_num.begin(), e_num.end());
	for (int i = 0; i < min(MAX, N); i++) {
		if (!e_num[i].first)continue;
		converter[e_num[i].second] = i;
		queue<int>Q;
		Q.push(0);
		while (!Q.empty()) {
			int cn = Q.front();
			Q.pop();
			for (auto j : edge[cn]) {
				if (lca.depth[cn] > lca.depth[j.to])continue;
				if (j.color != e_num[i].second) {
					dis[i][j.to] = dis[i][cn];
					num[i][j.to] = num[i][cn];
					Q.push(j.to);
				}
				else {
					dis[i][j.to] = dis[i][cn] + j.cost;
					num[i][j.to] = num[i][cn] + 1;
					Q.push(j.to);
				}
			}
		}
	}
	queue<int>Q;
	Q.push(0);
	while (!Q.empty()) {
		int cn = Q.front();
		Q.pop();
		for (auto i : edge[cn]) {
			if (lca.depth[cn] > lca.depth[i.to])continue;
			all_dis[i.to] = all_dis[cn] + i.cost;
			Q.push(i.to);
		}
	}
	for (auto p : q) {
		H = p.color;
		W = p.cost;
		L = p.l;
		R = p.r;
		H--;
		L--;
		R--;
		if (converter[H] == -1) {
			int c = lca.LCA(L, R);
			int ans = all_dis[L] + all_dis[R];
			ans -= all_dis[c] * 2;
			for (auto i : cedge[H]) {
				if (lca.LCA(i.to, L) == i.to && (lca.LCA(i.to, c)) == c)ans += W - i.cost;
				else if (lca.LCA(i.to, R) == i.to && (lca.LCA(i.to, c)) == c)ans += W - i.cost;
			}
			cout << ans << endl;
		}
		else {
			int c = lca.LCA(L, R);
			int ans = all_dis[L] + all_dis[R];
			ans -= all_dis[c] * 2;
			int index = converter[H];
			int add = num[index][L] + num[index][R] - num[index][c] * 2;
			add *= W;
			ans += add;
			ans -= dis[index][L] + dis[index][R] - dis[index][c] * 2;
			cout << ans << endl;
		}
	}
}