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.15.1) (judge verdict: Accepted)

use std::io::prelude::*;

fn input<T: std::str::FromStr>() -> T {
    let stdin = std::io::stdin();
    let token: String = stdin
        .lock()
        .bytes()
        .map(|c| c.unwrap() as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().unwrap()
}

fn main() {
    let n: usize = input();
    let q: usize = input();
    let abcd: Vec<(usize, usize, usize, i64)> = (0..n - 1)
        .map(|_| (input(), input(), input(), input()))
        .collect();
    let xyuv: Vec<(usize, i64, usize, usize)> = (0..q)
        .map(|_| (input(), input(), input(), input()))
        .collect();

    let mut g = LowestCommonAncestor::new(n);
    let mut e = vec![vec![]; n];
    for (a, b, c, d) in abcd {
        let (a, b) = (a - 1, b - 1);
        e[a].push((b, c, d));
        e[b].push((a, c, d));
        g.add_edge(a, b, d);
    }
    g.init();

    let mut col = vec![(0, 0); n];
    let mut color = vec![std::collections::HashMap::new(); n];
    for i in 0..q {
        let (x, _, u, v) = xyuv[i];
        let (u, v) = (u - 1, v - 1);
        let c = g.lca(u, v);
        color[u].entry(x).or_insert((0, 0));
        color[v].entry(x).or_insert((0, 0));
        color[c].entry(x).or_insert((0, 0));
    }
    dfs(0, n, &e, &mut col, &mut color);

    for i in 0..q {
        let (x, y, u, v) = xyuv[i];
        let (u, v) = (u - 1, v - 1);
        let c = g.lca(u, v);
        let mut ans = g.dist[u] + g.dist[v] - 2 * g.dist[c];
        ans -= color[u][&x].1 + color[v][&x].1 - 2 * color[c][&x].1;
        ans += (color[u][&x].0 + color[v][&x].0 - 2 * color[c][&x].0) * y;
        println!("{}", ans);
    }
}

fn dfs(
    cur: usize,
    p: usize,
    e: &Vec<Vec<(usize, usize, i64)>>,
    now: &mut Vec<(i64, i64)>,
    color: &mut Vec<std::collections::HashMap<usize, (i64, i64)>>,
) {
    for (&c, col) in color[cur].iter_mut() {
        *col = now[c];
    }
    for &(next, c, d) in &e[cur] {
        if next != p {
            now[c].0 += 1;
            now[c].1 += d;
            dfs(next, cur, e, now, color);
            now[c].0 -= 1;
            now[c].1 -= d;
        }
    }
}

#[derive(Clone, Debug)]
struct LowestCommonAncestor<T> {
    n: usize,
    p: usize,
    edge: Vec<Vec<(usize, T)>>,
    depth: Vec<usize>,
    dist: Vec<T>,
    parent: Vec<Vec<usize>>,
}

impl<T: Clone + Copy + Default + std::ops::Add<Output = T>> LowestCommonAncestor<T> {
    fn new(n: usize) -> LowestCommonAncestor<T> {
        let mut p = 0;
        while (1 << p) < n {
            p += 1;
        }
        LowestCommonAncestor {
            n: n,
            p: p,
            edge: vec![vec![]; n],
            depth: vec![0; n],
            dist: vec![T::default(); n],
            parent: vec![vec![n; p]; n + 1],
        }
    }

    fn add_edge(&mut self, u: usize, v: usize, d: T) {
        self.edge[u].push((v, d));
        self.edge[v].push((u, d));
    }

    fn init(&mut self) {
        let n = self.n;
        self.dfs(0, 0, T::default(), n);
        for i in 0..self.p - 1 {
            for v in 0..self.n {
                let p = self.parent[self.parent[v][i]][i];
                self.parent[v][i + 1] = p;
            }
        }
    }

    fn dfs(&mut self, u: usize, d: usize, w: T, p: usize) {
        if p != self.n {
            self.parent[u][0] = p;
        }
        self.depth[u] = d;
        self.dist[u] = w;
        for i in 0..self.edge[u].len() {
            let (v, vw) = self.edge[u][i];
            if v != p {
                self.dfs(v, d + 1, w + vw, u);
            }
        }
    }

    fn lca(&self, u: usize, v: usize) -> usize {
        let mut u = u;
        let mut v = v;
        if self.depth[u] > self.depth[v] {
            let t = u;
            u = v;
            v = t;
        }
        let mut diff = self.depth[v] - self.depth[u];
        for i in (0..self.p).rev() {
            let d = 1 << i;
            if d <= diff {
                diff -= d;
                v = self.parent[v][i];
            }
        }
        for i in (0..self.p).rev() {
            let pu = self.parent[u][i];
            let pv = self.parent[v][i];
            if pu != pv {
                u = pu;
                v = pv;
            }
        }
        if u == v {
            u
        } else {
            self.parent[u][0]
        }
    }
}