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 Rust (1.42.0) (judge verdict: Accepted)

#![allow(unused, non_snake_case, dead_code, non_upper_case_globals)]
use {
    proconio::{marker::*, *},
    std::{cmp::*, collections::*, mem::*},
};

#[fastout]
fn main() {
    input! {// //
           n:usize,q:usize,
        abcd:[(Usize1,Usize1,Usize1,usize);n-1],
        xyuv:[(Usize1,usize,Usize1,Usize1);q],
    }

    /*
    lca(u,v) = a とすると
    dist(u,v) = dist[u]+dist[v] - 2dist[a]

    色 x_i のすべての辺の長さが y_i に変更されたときの dist[u_i]
    , dist[v_i]
    , dist[a_i] を求める。

    */
    let mut g = vec![vec![]; n];
    let mut e = vec![vec![]; n];
    let mut G = vec![vec![]; n];
    for (i, &(a, b, c, d)) in abcd.iter().enumerate() {
        g[a].push(b);
        g[b].push(a);
        e[a].push((b, d, c));
        e[b].push((a, d, c));
        G[a].push((b, i));
        G[b].push((a, i));
    }
    let mut lca = LCA::new(&g);
    // lca.lca(u,v)
    let mut dist = vec![!0; n];
    let mut que = Vec::new();
    que.push((0, 0));
    while let Some(x) = que.pop() {
        let (now, dis) = x;
        dist[now] = dis;
        for &(nb, nd, nc) in e[now].iter() {
            if dist[nb] == !0 {
                que.push((nb, dis + nd));
            }
        }
    }
    dbg!(&dist);
    // dbg!(&lca.lca(3, 4));
    // dbg!(&lca.lca(2, 4));
    // dbg!(&lca.lca(1, 4));
    let mut W = vec![vec![]; n];
    for (i, &(x, y, u, v)) in xyuv.iter().enumerate() {
        W[u].push((i, x, y, 1));
        W[v].push((i, x, y, 1));
        W[lca.lca(u, v)].push((i, x, y, -2));
    }
    let mut d = D {
        W: W,
        ans: vec![0; q],
        sum: vec![0; n],
        cnt: vec![0; n],
        e: e,
    };
    d.dfs(0, !0, 0);
    // d.dfs(0, !0);
    for &a in d.ans.iter() {
        println!("{}", a);
    }

    // let mut ans = vec![0; q];
}
struct D {
    // u: usize,
    // p: usize,
    W: Vec<Vec<(usize, usize, usize, i64)>>,
    ans: Vec<i64>,
    sum: Vec<i64>,
    cnt: Vec<i64>,
    e: Vec<Vec<(usize, usize, usize)>>,
}
impl D {
    fn dfs(&mut self, v: usize, pre: usize, dep: usize) {
        for &(nx, dis, col) in self.e[v].clone().iter() {
            if nx == pre {
                continue;
            }
            self.cnt[col] += 1;
            self.sum[col] += dis as i64;
            self.dfs(nx, v, dep + dis);
            self.cnt[col] -= 1;
            self.sum[col] -= dis as i64;
        }
        for &(idx, col, dist, cf) in self.W[v].iter() {
            self.ans[idx] += cf * (dep as i64 + -self.sum[col] + self.cnt[col] * dist as i64);
        }
    }

    // fn dfs(&mut self, u: usize, p: usize) {
    //     for &(id, color, y, coeff) in self.W[u].iter() {
    //         self.ans[id] += coeff * (-self.sum[color] + self.cnt[color] * y as i64);
    //     }
    //     for (dst, cost, color) in self.e[u].clone() {
    //         if dst == p {
    //             continue;
    //         }
    //         self.sum[color] += cost as i64;
    //         self.cnt[color] += 1;
    //         self.dfs(dst, u);
    //     }
    // }
}

pub struct LCA {
    pub depth: Vec<usize>,
    pub parent: Vec<Vec<Option<usize>>>,
}
impl LCA {
    pub fn new(g: &[Vec<usize>]) -> LCA {
        LCA::with_root(0, g)
    }
    pub fn with_root(root: usize, g: &[Vec<usize>]) -> LCA {
        fn dfs(
            i: usize,
            p: Option<usize>,
            d: usize,
            g: &[Vec<usize>],
            depth: &mut [usize],
            parent: &mut [Vec<Option<usize>>],
        ) {
            parent[i][0] = p;
            depth[i] = d;
            for &t in &g[i] {
                if Some(t) != p {
                    dfs(t, Some(i), d + 1, g, depth, parent);
                }
            }
        }
        let n = g.len();
        let l2 = (1..).find(|i| 1usize << i > n).unwrap();
        let mut depth = vec![0; n];
        let mut parent = vec![vec![None; l2 + 1]; n];
        dfs(root, None, 0, &g, &mut depth, &mut parent);
        for i in 1..l2 + 1 {
            for j in 0..n {
                if let Some(p) = parent[j][i - 1] {
                    parent[j][i] = parent[p][i - 1];
                }
            }
        }
        LCA { depth, parent }
    }
    pub fn lca(&self, mut a: usize, mut b: usize) -> usize {
        use std::mem::swap;
        if self.depth[b] < self.depth[a] {
            swap(&mut a, &mut b);
        }
        while self.depth[a] != self.depth[b] {
            b = self.parent[b][(self.depth[b] - self.depth[a]).trailing_zeros() as usize].unwrap();
        }
        if a == b {
            return a;
        }
        for i in (0..self.parent[0].len()).rev() {
            if self.parent[a][i] != self.parent[b][i] {
                a = self.parent[a][i].unwrap();
                b = self.parent[b][i].unwrap();
            }
        }
        self.parent[a][0].unwrap()
    }
}