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 Kotlin (1.3.71) (judge verdict: Accepted)

import java.io.*
import java.util.*
import java.lang.Math.*


class LCA(val N: Int) {
    private val to = Array(N){ArrayList<Int>()}
    private val co = Array(N){ArrayList<Long>()}
    private val dep = IntArray(N){0}
    private val costs = LongArray(N){0}
    private var l = 0
    private val par = Array(N+1){ArrayList<Int>()}
    private var root = 0
    init {
        while ((1 shl l) < N) {
            l++
        }
        par.forEach { it.addAll(List(this.l){0}) }
    }
    fun addEdge(s: Int, t: Int, cost: Long=1L) {
        to[s].add(t)
        co[s].add(cost)
        to[t].add(s)
        co[t].add(cost)
    }
    private fun dfs(x: Int, d: Int=0, cost: Long=0L, p: Int=-1) {
        if (p != -1) {
            this.par[x][0] = p
        }
        this.dep[x] = d
        this.costs[x] = cost
        for (i in 0 until to[x].size) {
            val u = this.to[x][i]
            if (u == p)
                continue
            else
                dfs(u, d+1, cost+this.co[x][i], x)
        }
    }
    fun biuld(root: Int = 0) {
        this.root = root
        dfs(root)
        for (i in 0 until this.l - 1) {
            for (x in 0 until N) {
                this.par[x][i+1] = par[par[x][i]][i]
            }
        }
    }
    fun lca(a: Int, b: Int): Int {
        var a = a; var b = b
        if (dep[a] > dep[b]) {
            a = b.also{b = a}
        }
        var gap = dep[b] - dep[a]
        for (i in this.l - 1 downTo 0) {
            val len = 1 shl i
            if (gap >= len) {
                gap -= len
                b = par[b][i]
            }
        }
        if (a == b) {
            return a
        }
        for (i in this.l-1 downTo 0) {
            val na = par[a][i]
            val nb = par[b][i]
            if (na != nb) {
                a = na; b = nb
            }
        }
        return par[a][0]
    }
    fun length(a: Int, b: Int): Int {
        val c = lca(a, b)
        return dep[a] + dep[b] - dep[c] * 2
    }
    fun distance(a: Int, b: Int, common: Int=-1): Long {
        val c = if (common<0) this.lca(a, b) else common
        return costs[a] + costs[b] - costs[c] * 2
    }
}


fun main() {
    val (N,Q) = rd.readIntArray()
    val gr = LCA(N)
    val egs = Array(N){ArrayList<To>()}
    for (i in 0 until N-1) {
        var (a, b, col, dst) = rd.readIntArray()
        a--;b--
        egs[a].add(To(b, dst.toLong(), col))
        egs[b].add(To(a, dst.toLong(), col))
        gr.addEdge(a, b, dst.toLong())
    }
    gr.biuld()

    data class Query(val cx: Int, val qid: Int, val coeff: Int, val dy: Long)
    val ans = LongArray(Q){0}
    val qrys = Array(N){ArrayList<Query>()}
    for (q in 0 until Q) {
        var (cx, dy, a, b) = rd.readIntArray()
        a--; b--

        val lca = gr.lca(a, b)
        ans[q] = gr.distance(a, b, lca)

        qrys[a].add(Query(cx, q, 1, dy.toLong()))
        qrys[b].add(Query(cx, q, 1, dy.toLong()))
        qrys[lca].add(Query(cx, q, -2, dy.toLong()))
    }

    val cnt = IntArray(N){0}
    val sum = LongArray(N){0L}

    fun dfs(v: Int, p: Int=-1) {
        for (qr in qrys[v]) {
            val (col,qid, coeff, dist) = qr
            var x = -sum[col]
            x += dist * cnt[col]
            ans[qid] += x * coeff
        }

        for (eg in egs[v]) {
            val (to, cost, col) = eg
            if (to == p) continue

            cnt[col] += 1
            sum[col] += cost
            dfs(to, v)
            cnt[col] -= 1
            sum[col] -= cost
        }
    }

    dfs(0)
    for (q in 0 until Q) {
        println(ans[q])
    }
}


//val rd = debug.Reader("abc", "171", "f", "sample-1")
val rd = Reader()
fun main(args: Array<String>) {
    Thread(null, MainThread(), "mainThread", 128 * 1024 * 1024).start()
}


const val MOD = 1_000_000_007L; const val INF = Int.MAX_VALUE/2; const val LINF = Long.MAX_VALUE/2
const val EPS = 1e-9; fun DBLEQ(a: Double, b: Double): Boolean {return abs(a - b) < EPS}
data class IntPair(val first: Int, val second: Int)
data class To(val idx: Int, val cost: Long, val col: Int)
fun <T>edge(V: Int): Array<ArrayList<T>> { return Array(V){ArrayList<T>()} }
val errPrintln: (Any) -> Unit = { msg -> System.err.println(msg) }
class MainThread : Runnable {
    override fun run() { main() }
}
class Reader {
    private val br = BufferedReader(InputStreamReader(System.`in`))
    val readString: () -> String = { br.readLine() }
    val readInt: () -> Int = { br.readLine().toInt() }
    val readLong: () -> Long = { br.readLine().toLong() }
    val readIntArray: () -> IntArray = { br.readLine().split(' ').map { it.toInt() }.toIntArray() }
    val readLongArray: () -> LongArray = { br.readLine().split(' ').map { it.toLong() }.toLongArray() }
    val readListInt: () -> List<Int> = { br.readLine().split(' ').map { it.toInt() } }
    val readListLong: () -> List<Long> = { br.readLine().split(' ').map { it.toLong() } }
}