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)

#[allow(dead_code)]
mod persistent_array {
    use std::cmp::Ordering;
    use std::rc::Rc;
    pub struct Head<T: Clone> {
        root: Link<T>,
    }
    impl<T: Clone> Head<T> {
        pub fn new(n: usize, ini: T) -> Head<T> {
            Head {
                root: Node::build_by(&vec![ini; n])
            }
        }
        pub fn build_by(a: &[T]) -> Head<T> {
            Head {
                root: Node::build_by(a),
            }
        }
        pub fn get_at(&self, k: usize) -> Option<&T> {
            Node::get_at(&self.root, k)
        }
        pub fn set_at(&self, k: usize, val: T) -> Head<T> {
            let r = self.root.clone();
            Head {
                root: Node::set_at(r, k, val),
            }
        }
    }
    type Link<T> = Option<Rc<Node<T>>>;
    struct Node<T: Clone> {
        val: T,
        size: usize,
        left: Link<T>,
        right: Link<T>,
    }
    impl<T: Clone> Node<T> {
        fn get_size(t: &Link<T>) -> usize {
            match t.as_ref() {
                None => 0,
                Some(t) => t.size,
            }
        }
        fn new_node(l: Link<T>, r: Link<T>, val: T) -> Link<T> {
            Some(Rc::new(Node {
                val: val,
                size: Node::get_size(&l) + Node::get_size(&r) + 1,
                left: l,
                right: r,
            }))
        }
        fn build_by(a: &[T]) -> Link<T> {
            if a.len() == 0 {
                None
            } else if a.len() == 1 {
                Node::new_node(None, None, a[0].clone())
            } else {
                let n = a.len();
                let m = n / 2;
                Node::new_node(Node::build_by(&a[..m]), Node::build_by(&a[(m + 1)..]), a[m].clone())
            }
        }
        fn get_at(t: &Link<T>, k: usize) -> Option<&T> {
            assert!(k < Node::get_size(t));
            let t = t.as_ref().unwrap();
            let l_size = Node::get_size(&t.left);
            match l_size.cmp(&k) {
                Ordering::Equal => {
                    Some(&t.val)
                },
                Ordering::Greater => {
                    Node::get_at(&t.left, k)
                },
                Ordering::Less => {
                    Node::get_at(&t.right, k - l_size - 1)
                },
            }
        }
        fn set_at(t: Link<T>, k: usize, val: T) -> Link<T> {
            assert!(k < Node::get_size(&t));
            let t = t.unwrap();
            let l_size = Node::get_size(&t.left);
            match l_size.cmp(&k) {
                Ordering::Equal => {
                    Node::new_node(t.left.clone(), t.right.clone(), val)
                },
                Ordering::Greater => {
                    let l = Node::set_at(t.left.clone(), k, val);
                    Node::new_node(l, t.right.clone(), t.val.clone())
                }
                Ordering::Less => {
                    let r = Node::set_at(t.right.clone(), k - l_size - 1, val);
                    Node::new_node(t.left.clone(), r, t.val.clone())
                },
            }
        }
    }
}
use std::io::{Read, Write};

fn calc_lca(mut a: usize, mut b: usize, db: &Vec<Vec<usize>>, depth: &[usize]) -> usize {
    if depth[a] > depth[b] {
        std::mem::swap(&mut a, &mut b);
    }
    for i in (0..db.len()).rev() {
        if ((depth[b] - depth[a]) >> i) & 1 == 1 {
            b = db[i][b];
        }
    }
    if a == b {
        return a;
    }
    for i in (0..db.len()).rev() {
        if db[i][a] != db[i][b] {
            a = db[i][a];
            b = db[i][b];
        }
    }
    db[0][a]
}

fn run() {
    let mut s = String::new();
    std::io::stdin().read_to_string(&mut s).unwrap();
    let mut it = s.trim().split_whitespace();
    let n: usize = it.next().unwrap().parse().unwrap();
    let q: usize = it.next().unwrap().parse().unwrap();
    let mut g = vec![vec![]; n];
    for _ in 1..n {
        let a = it.next().unwrap().parse::<usize>().unwrap() - 1;
        let b = it.next().unwrap().parse::<usize>().unwrap() - 1;
        let c = it.next().unwrap().parse::<usize>().unwrap() - 1;
        let d = it.next().unwrap().parse::<usize>().unwrap();
        g[a].push((b, c, d));
        g[b].push((a, c, d));
    }
    let mut parent = vec![0; n];
    let mut depth = vec![0; n];
    let mut dp = vec![0; n];
    let mut h: Vec<Option<persistent_array::Head<(usize, usize)>>> = (0..n).map(|_| None).collect();
    h[0] = Some(persistent_array::Head::new(n - 1, (0, 0)));
    let mut stack = vec![0];
    while let Some(v) = stack.pop() {
        for &(u, c, d) in &g[v] {
            if u == parent[v] {
                continue;
            }
            parent[u] = v;
            depth[u] = depth[v] + 1;
            dp[u] = dp[v] + d;
            let t = h[v].take().unwrap();
            let &(cnt, sum) = t.get_at(c).unwrap();
            let s = t.set_at(c, (cnt + 1, sum + d));
            h[u] = Some(s);
            h[v] = Some(t);
            stack.push(u);
        }
    }
    let mut doubling = vec![parent];
    for i in 1..17 {
        doubling.push(vec![0; n]);
        for j in 0..n {
            doubling[i][j] = doubling[i - 1][doubling[i - 1][j]];
        }
    }
    let out = std::io::stdout();
    let mut out = std::io::BufWriter::new(out.lock());
    for _ in 0..q {
        let x = it.next().unwrap().parse::<usize>().unwrap() - 1;
        let y = it.next().unwrap().parse::<usize>().unwrap();
        let u = it.next().unwrap().parse::<usize>().unwrap() - 1;
        let v = it.next().unwrap().parse::<usize>().unwrap() - 1;
        let mut ans = 0;
        for &v in [u, v].iter() {
            let &(cnt, sum) = (&h[v]).as_ref().unwrap().get_at(x).unwrap();
            ans += dp[v] - sum + cnt * y;
        }
        let p = calc_lca(u, v, &doubling, &depth);
        let &(cnt, sum) = (&h[p]).as_ref().unwrap().get_at(x).unwrap();
        ans -= 2 * (dp[p] - sum + cnt * y);
        writeln!(out, "{}", ans).unwrap();
    }
}

fn main() {
    run();
}