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 Go (1.6) (judge verdict: Runtime Error)

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	var n, q int
	fmt.Scan(&n)
	fmt.Scan(&q)

	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)

	nodes := make([][][]int, n)
	for i := 0; i < n; i++ {
		nodes[i] = [][]int{}
	}

	for i := 0; i < n-1; i++ {
		scanner.Scan()
		a, _ := strconv.Atoi(scanner.Text())
		scanner.Scan()
		b, _ := strconv.Atoi(scanner.Text())
		scanner.Scan()
		c, _ := strconv.Atoi(scanner.Text())
		scanner.Scan()
		d, _ := strconv.Atoi(scanner.Text())
		a--
		b--
		c--
		nodes[a] = append(nodes[a], []int{b, c, d})
		nodes[b] = append(nodes[b], []int{a, c, d})
	}

	log2n := 17
	parents := make([][]int, n)
	depths := make([]int, n)
	for i := 0; i < n; i++ {
		parents[i] = make([]int, log2n+1)
	}

	queues := [][]int{
		{0, 0, 0},
	}
	for len(queues) > 0 {
		node := queues[0][0]
		parent := queues[0][1]
		depth := queues[0][2]

		parents[node][0] = parent
		depths[node] = depth

		for i := 0; i < len(nodes[node]); i++ {
			if nodes[node][i][0] == parent {
				continue
			}
			queues = append(queues, []int{nodes[node][i][0], node, depth + 1})
		}

		queues = queues[1:]
	}

	for i := 1; i <= log2n; i++ {
		for j := 0; j < n; j++ {
			parents[j][i] = parents[parents[j][i-1]][i-1]
		}
	}

	x := make([]int, q)
	y := make([]int, q)
	u := make([]int, q)
	v := make([]int, q)
	lca := make([]int, q)
	need := make([]map[int]bool, n)
	for i := 0; i < n; i++ {
		need[i] = make(map[int]bool)
	}

	for i := 0; i < q; i++ {
		scanner.Scan()
		x[i], _ = strconv.Atoi(scanner.Text())
		x[i]--
		scanner.Scan()
		y[i], _ = strconv.Atoi(scanner.Text())
		scanner.Scan()
		u[i], _ = strconv.Atoi(scanner.Text())
		u[i]--
		scanner.Scan()
		v[i], _ = strconv.Atoi(scanner.Text())
		v[i]--

		uu := u[i]
		vv := v[i]
		xx := x[i]
		if depths[uu] > depths[vv] {
			uu, vv = vv, uu
		}

		a := uu
		b := vv
		diff := depths[vv] - depths[uu]
		for j := uint(0); j <= uint(log2n); j++ {
			if (diff>>j)&1 == 1 {
				b = parents[b][j]
			}
		}
		for j := log2n; j >= 0; j-- {
			if parents[a][j] != parents[b][j] {
				a = parents[a][j]
				b = parents[b][j]
			}
		}
		lca[i] = parents[a][0]

		need[uu][xx] = true
		need[vv][xx] = true
		need[lca[i]][xx] = true
 	}

	prefixSum := make([]int64, n)
	totalColorCount := make([]int, n-1)
	totalColorDist := make([]int64, n-1)
	prefixColorCount := make([][]int, n)
	prefixColorDist := make([][]int64, n)
	for i := 0; i < n; i++ {
		prefixColorCount[i] = make([]int, n-1)
		prefixColorDist[i] = make([]int64, n-1)
	}

	var dfs func(node int, parent int)
	dfs = func(node int, parent int) {
		for c := range need[node] {
			prefixColorCount[node][c] = totalColorCount[c]
			prefixColorDist[node][c] = totalColorDist[c]
		}

		for i := 0; i < len(nodes[node]); i++ {
			child := nodes[node][i][0]
			if child == parent {
				continue
			}

			c := nodes[node][i][1]
			d := nodes[node][i][2]

			prefixSum[child] = prefixSum[node] + int64(d)

			totalColorCount[c]++
			totalColorDist[c] += int64(d)
			dfs(child, node)
			totalColorCount[c]--
			totalColorDist[c] -= int64(d)
		}
	}
	dfs(0, 0)

	/*
	queues = [][]int{{0, 0, 0, -1, 0}}
	for len(queues) > 0 {
		op := queues[0][0]
		node := queues[0][1]
		parent := queues[0][2]
		color := queues[0][3]
		dist := queues[0][4]

		queues = queues[1:]

		if op == 0 {
			if color != -1 {
				totalColorCount[color]++
				totalColorDist[color] += int64(dist)
			}

			for c := range need[node] {
				prefixColorCount[node][c] = totalColorCount[c]
				prefixColorDist[node][c] = totalColorDist[c]
			}

			for i := 0; i < len(nodes[node]); i++ {
				child := nodes[node][i][0]
				if child == parent {
					continue
				}

				c := nodes[node][i][1]
				d := nodes[node][i][2]

				prefixSum[child] = prefixSum[node] + int64(d)

				queues = append([][]int{{0, child, node, c, d}, {1, child, node, c, d}}, queues...)
			}
		} else {
			totalColorCount[color]--
			totalColorDist[color] -= int64(dist)
		}
	}
	 */

	for i := 0; i < q; i++ {
		uu := u[i]
		vv := v[i]
		xx := x[i]
		yy := y[i]
		ll := lca[i]

		du := prefixSum[uu] - prefixColorDist[uu][xx] + int64(prefixColorCount[uu][xx]*yy)
		dv := prefixSum[vv] - prefixColorDist[vv][xx] + int64(prefixColorCount[vv][xx]*yy)
		dlca := prefixSum[ll] - prefixColorDist[ll][xx] + int64(prefixColorCount[ll][xx]*yy)
		d := du + dv - 2*dlca
		fmt.Println(d)
	}
}