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-----
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-----
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.

```python

USER_FILENAME = "<user_code>"
import sys, json, builtins
import math, heapq, bisect, itertools, functools, collections, statistics, fractions, decimal, operator, array, random, re, string, os, pathlib
try:
    import resource as _res
except Exception:
    _res = None
from collections import Counter, defaultdict, deque, OrderedDict
from functools import lru_cache, reduce
from itertools import accumulate, permutations, combinations, product
from math import gcd, ceil, floor, sqrt
from decimal import Decimal
try:
    from typing import *
except Exception:
    pass
try:
    sys.setrecursionlimit(1_000_000)
except Exception:
    pass
try:
    import site as _site
    try:
        _sys_sites = _site.getsitepackages() if hasattr(_site, "getsitepackages") else []
        for _p in _sys_sites:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
    try:
        _usp = _site.getusersitepackages()
        if isinstance(_usp, str):
            _usp = [_usp]
        for _p in _usp:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
except Exception:
    pass

ns = {"__name__": "__main__"}
for _k, _v in list(globals().items()):
    if not _k.startswith("_"):
        ns[_k] = _v
_CODE = 'import sys\nfrom itertools import combinations, permutations, product, combinations_with_replacement, accumulate\nfrom heapq import heapify, heappop, heappush, heappushpop\nfrom bisect import bisect_left, bisect_right\nfrom collections import Counter, defaultdict, deque\nfrom math import sqrt, log, floor, ceil, factorial, cos, sin, pi  # , gcd\nfrom fractions import gcd\nfrom operator import mul\nfrom functools import reduce\n\nsys.setrecursionlimit(10 ** 8)\ninput = sys.stdin.readline\nINF = float(\'inf\')\nLINF = 2 ** 63 - 1\nNIL = -LINF\nMOD = 10 ** 9 + 7\nMGN = 4\n\n\ndef AST(exp: bool, msg: str = ""): assert exp, msg\n\n\ndef TAST(exp: bool, msg=""):\n    if exp is False: print("TAssertionError:", msg)\n    while exp is False:\n        pass\n\n\ndef EPR(msg): print(msg, file=sys.stderr)\n\n\ndef II(): return int(input())\n\n\ndef IF(): return float(input())\n\n\ndef IS(): return input().replace(\'\\n\', \'\')\n\n\ndef ILCI(n: int): return [II() for _ in range(n)]\n\n\ndef ILCF(n: int): return [IF() for _ in range(n)]\n\n\ndef ILI(): return list(map(int, input().split()))\n\n\ndef ILLI(n: int): return [[int(j) for j in input().split()] for i in range(n)]\n\n\ndef ILF(): return list(map(float, input().split()))\n\n\ndef ILLF(n: int): return [[float(j) for j in input().split()] for i in range(n)]\n\n\ndef LTOS(lst: list, sep: str = \' \'): return sep.join(map(str, lst))\n\n\ndef DEC(lst: list): return list(map(lambda x: x - 1, lst))\n\n\ndef INC(lst: list): return list(map(lambda x: x + 1, lst))\n\n\nclass Queue:\n    def __init__(self) -> None:\n        self.items = deque()\n\n    def is_empty(self) -> bool:\n        return len(self.items) == 0\n\n    def enqueue(self, item) -> None:\n        self.items.appendleft(item)\n\n    def insert(self, item) -> None:\n        self.enqueue(item)\n\n    def dequeue(self):\n        return self.items.pop()\n\n    def front(self):\n        return self.items[-1]\n\n    def pop(self) -> None:\n        self.items.pop()\n\n    def size(self) -> int:\n        return len(self.items)\n\n\nclass LCA:\n    def __init__(self, N: int) -> None:\n        self.N = N\n        self.to = [[] for _ in range(N)]\n        self.co = [[] for _ in range(N)]\n        self.dep = [0] * N\n        self.costs = [0] * N\n        l = 0\n        while (1 << l) < N:\n            l += 1\n        self.l = l\n        self.par = [([0] * l) for _ in range(N + 1)]\n\n    def add_edge(self, a: int, b: int, c=0) -> None:\n        self.to[a].append(b)\n        self.co[a].append(c)\n        self.to[b].append(a)\n        self.co[b].append(c)\n\n    \'\'\'\n    def _dfs(self, v: int, d: int = 0, c = 0, p: int = -1) -> None:\n        if p != -1:\n            self.par[v][0] = p\n        self.dep[v] = d\n        self.costs[v] = c\n        for i in range(len(self.to[v])):\n            u = self.to[v][i]\n            if u == p:\n                continue\n            else:\n                self._dfs(u, d+1, c+self.co[v][i], v)\n    \'\'\'\n\n    def _bfs(self, root: int) -> None:\n        que = Queue()\n        que.enqueue(root)\n        self.dep[root] = 0\n        self.costs[root] = 0\n        vis = [False] * self.N\n        while que.is_empty() is False:\n            v = que.dequeue()\n            vis[v] = True\n            nd = self.dep[v] + 1\n            cs = self.costs[v]\n            for i in range(len(self.to[v])):\n                nv = self.to[v][i]\n                if vis[nv]:\n                    continue\n                else:\n                    que.enqueue(nv)\n                    self.dep[nv] = nd\n                    self.costs[nv] = cs + self.co[v][i]\n                    self.par[nv][0] = v\n\n    def init(self, root: int = 0) -> None:\n        self.root = root\n        self._bfs(root)\n        for i in range(self.l - 1):\n            for v in range(self.N):\n                self.par[v][i + 1] = self.par[self.par[v][i]][i]\n\n    def lca(self, a: int, b: int) -> int:\n        dep_s, dep_l = self.dep[a], self.dep[b]\n        if dep_s > dep_l:\n            a, b = b, a\n            dep_s, dep_l = dep_l, dep_s\n        gap = dep_l - dep_s\n        L_1 = self.l - 1\n        par = self.par\n        for i in range(L_1, -1, -1):\n            leng = 1 << i\n            if gap >= leng:\n                gap -= leng\n                b = par[b][i]\n        if a == b:\n            return a\n        for i in range(L_1, -1, -1):\n            na = par[a][i]\n            nb = par[b][i]\n            if na != nb:\n                a, b = na, nb\n        return par[a][0]\n\n    def length(self, a: int, b: int) -> int:\n        c = self.lca(a, b)\n        dep = self.dep\n        return dep[a] + dep[b] - dep[c] * 2\n\n    def dist(self, a: int, b: int):\n        c = self.lca(a, b)\n        costs = self.costs\n        return costs[a] + costs[b] - costs[c] * 2\n\n\ndef main():\n    N, Q = ILI()\n    gr = LCA(N)\n    es = [[] for _ in range(N)]\n    for i in range(N - 1):\n        a, b, col, dist = ILI()\n        a -= 1;\n        b -= 1\n        es[a].append((b, dist, col))\n        es[b].append((a, dist, col))\n        gr.add_edge(a, b, dist)\n\n    gr.init()\n    ans = [0] * Q\n    qs = [[] for _ in range(N)]\n    for i in range(Q):\n        cx, dy, a, b = ILI()\n        a -= 1;\n        b -= 1\n        # ans[i] = gr.dist(a, b)\n        c = gr.lca(a, b)\n        ans[i] = gr.costs[a] + gr.costs[b] - gr.costs[c] * 2\n        qs[a].append((cx, i, 1, dy))\n        qs[b].append((cx, i, 1, dy))\n        qs[c].append((cx, i, -2, dy))\n\n    cnt = [0] * N\n    sum_ = [0] * N\n\n\n    def dfs(v: int, p: int = -1) -> None:\n        for (col, qid, coeff, dist) in qs[v]:\n            x = -sum_[col]\n            x += dist * cnt[col]\n            ans[qid] += x * coeff\n\n        for (to, co, col) in es[v]:\n            if to == p:\n                continue\n            cnt[col] += 1\n            sum_[col] += co\n\n            dfs(to, v)\n\n            cnt[col] -= 1\n            sum_[col] -= co\n\n\n    sk = []\n    tr = [{} for _ in range(N+1)]\n    vis = [False] * (N+1)\n\n    def dfs2(v: int, p: int = -1) -> None:\n        for (col, qid, coeff, dist) in qs[v]:\n            x = -sum_[col]\n            x += dist * cnt[col]\n            ans[qid] += x * coeff\n\n        vis[v] = True\n\n        for (to, co, col) in reversed(es[v]):\n            if to == p:\n                continue\n            sk.append((to, v, col, co))\n            tr[v][to] = (col, co)\n\n        while len(sk) > 0:\n            v, p, cl, cs = sk[-1]\n            if len(es[v]) == 1:\n                sk.pop()\n\n            if vis[v] and p >= 0:\n                cl, cs = tr[p][v]\n                cnt[cl] -= 1\n                sum_[cl] -= cs\n                tr[p].pop(v)\n                sk.pop()\n                continue\n\n            cnt[cl] += 1\n            sum_[cl] += cs\n\n            for (col, qid, coeff, dist) in qs[v]:\n                x = -sum_[col]\n                x += dist * cnt[col]\n                ans[qid] += x * coeff\n\n            vis[v] = True\n\n            for (to, co, col) in reversed(es[v]):\n                if to == p:\n                    continue\n                sk.append((to, v, col, co))\n                tr[v][to] = (col, co)\n\n            if len(tr[v]) == 0 and p >= 0:\n                cl, cs = tr[p][v]\n                cnt[cl] -= 1\n                sum_[cl] -= cs\n                tr[p].pop(v)\n\n    dfs2(0)\n\n    print(*ans, sep=\'\\n\')\n\n\ndef __starting_point():\n    main()\n\n__starting_point()'
_co = compile(_CODE, USER_FILENAME, "exec")
exec(_co, ns, ns)

```

Measured memory_bytes: