macro_rules ! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; ( iter = $ iter : ident , $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut $ iter = s . split_whitespace ( ) ; input_inner ! { $ iter , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut iter = s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; }
macro_rules ! input_inner { ( $ iter : expr ) => { } ; ( $ iter : expr , ) => { } ; ( $ iter : expr , mut $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let mut $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , mut $ var : ident $ ( $ r : tt ) * ) => { input_inner ! { $ iter , mut $ var : usize $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident $ ( $ r : tt ) * ) => { input_inner ! { $ iter , $ var : usize $ ( $ r ) * } } ; }
macro_rules ! read_value { ( $ iter : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ iter , $ t ) ) ,* ) } ; ( $ iter : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ iter , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ iter : expr , { chars : $ base : expr } ) => { read_value ! ( $ iter , String ) . chars ( ) . map ( | c | ( c as u8 - $ base as u8 ) as usize ) . collect ::< Vec < usize >> ( ) } ; ( $ iter : expr , { char : $ base : expr } ) => { read_value ! ( $ iter , { chars : $ base } ) [ 0 ] } ; ( $ iter : expr , chars ) => { read_value ! ( $ iter , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ iter : expr , char ) => { read_value ! ( $ iter , chars ) [ 0 ] } ; ( $ iter : expr , usize1 ) => { read_value ! ( $ iter , usize ) - 1 } ; ( $ iter : expr , $ t : ty ) => { $ iter . next ( ) . unwrap ( ) . parse ::<$ t > ( ) . unwrap ( ) } ; }
pub struct SegmentTree<M: Monoid> {
    pub n: usize,
    pub seg: Vec<M::T>,
    pub m: M,
}
impl<M: Monoid> SegmentTree<M> {
    pub fn new(n: usize, m: M) -> SegmentTree<M> {
        let n = 1 << format!("{:b}", n - 1).len();
        let seg = vec![m.mempty(); 2 * n - 1];
        SegmentTree {
            n: n,
            seg: seg,
            m: m,
        }
    }
    pub fn from_vec(v: Vec<M::T>, m: M) -> SegmentTree<M> {
        let n = 1 << format!("{:b}", v.len() - 1).len();
        let mut seg = vec![m.mempty(); 2 * n - 1];
        for (i, x) in v.into_iter().enumerate() {
            seg[i + n - 1] = x;
        }
        for i in (0..n - 1).rev() {
            seg[i] = m.mappend(&seg[2 * i + 1], &seg[2 * i + 2]);
        }
        SegmentTree {
            n: n,
            seg: seg,
            m: m,
        }
    }
    pub fn update(&mut self, k: usize, x: M::T) {
        let mut k = k + self.n - 1;
        self.seg[k] = x;
        while k > 0 {
            k = (k - 1) / 2;
            self.seg[k] = self.m.mappend(&self.seg[2 * k + 1], &self.seg[2 * k + 2]);
        }
    }
    pub fn query(&self, l: usize, r: usize) -> M::T {
        let mut l = l + self.n - 1;
        let mut r = r + self.n - 1;
        let mut res = self.m.mempty();
        while l < r {
            if r & 1 == 0 {
                r -= 1;
                res = self.m.mappend(&res, &self.seg[r]);
            }
            if l & 1 == 0 {
                res = self.m.mappend(&res, &self.seg[l]);
                l += 1;
            }
            l = (l - 1) / 2;
            r = (r - 1) / 2;
        }
        res
    }
}
pub trait Monoid {
    type T: Clone + PartialEq;
    fn mempty(&self) -> Self::T;
    fn mappend(&self, x: &Self::T, y: &Self::T) -> Self::T;
}
pub struct MinMonoid<T: Ord + Clone> {
    min: T,
}
impl<T: Ord + Clone> MinMonoid<T> {
    pub fn new(min: T) -> MinMonoid<T> {
        MinMonoid { min: min }
    }
}
impl<T: Ord + Clone> Monoid for MinMonoid<T> {
    type T = T;
    fn mempty(&self) -> T {
        self.min.clone()
    }
    fn mappend(&self, x: &T, y: &T) -> T {
        std::cmp::min(x, y).clone()
    }
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Adjacent {
    to: usize,
    id: usize,
}
impl Adjacent {
    pub fn new(to: usize, id: usize) -> Adjacent {
        Adjacent { to: to, id: id }
    }
}
#[derive(Clone, Debug, Default)]
pub struct Graph {
    vsize: usize,
    esize: usize,
    graph: Vec<Vec<Adjacent>>,
}
impl Graph {
    pub fn new(vsize: usize) -> Graph {
        Graph {
            vsize: vsize,
            esize: 0,
            graph: vec![vec![]; vsize],
        }
    }
    pub fn add_edge(&mut self, from: usize, to: usize) {
        self.graph[from].push(Adjacent::new(to, self.esize));
        self.esize += 1;
    }
    pub fn add_undirected_edge(&mut self, u: usize, v: usize) {
        self.graph[u].push(Adjacent::new(v, self.esize));
        self.graph[v].push(Adjacent::new(u, self.esize));
        self.esize += 1;
    }
    pub fn vertexes(&self) -> std::ops::Range<usize> {
        0..self.vsize
    }
    pub fn adjacency(&self, from: usize) -> &Vec<Adjacent> {
        &self.graph[from]
    }
}
// pub mod euler_tour {
// use super::*;
#[derive(Clone, Debug, Default)]
pub struct Vertex {
    l: usize,
    r: usize,
    d: i64,
}
#[derive(Clone, Debug, Default)]
pub struct Edge {
    l: usize,
    r: usize,
    c: usize,
    d: usize,
}
#[derive(Debug, Default)]
pub struct EulerTour {
    graph: Graph,
    vs: Vec<Vertex>,
    es: Vec<Edge>,
    vtrace: Vec<usize>,
    etrace: Vec<usize>,
}
impl EulerTour {
    pub fn new(n: usize) -> EulerTour {
        EulerTour {
            vs: vec![Default::default(); n],
            graph: Graph::new(n),
            ..Default::default()
        }
    }
    pub fn add_edge(&mut self, from: usize, to: usize, c: usize, d: usize) {
        self.graph.add_undirected_edge(from, to);
        self.es.push(Edge {
            c: c,
            d: d,
            ..Default::default()
        });
    }
    pub fn build(&mut self) {
        self.euler_tour(0, std::usize::MAX, 0);
    }
    pub fn euler_tour(&mut self, u: usize, p: usize, d: i64) {
        self.vs[u].l = self.vtrace.len();
        self.vs[u].d = d;
        self.vtrace.push(u);
        for i in 0..self.graph.adjacency(u).len() {
            let a = self.graph.adjacency(u)[i];
            if a.to != p {
                self.es[a.id].l = self.etrace.len();
                self.etrace.push(a.id);
                self.euler_tour(a.to, u, d + 1);
                self.vtrace.push(u);
                self.es[a.id].r = self.etrace.len();
                self.etrace.push(a.id);
            }
        }
        self.vs[u].r = self.vtrace.len() - 1;
    }
    pub fn ancestor(&self, u: usize, v: usize) -> usize {
        if u >= self.vs.len() {
            v
        } else if v >= self.vs.len() {
            u
        } else if self.vs[u].d < self.vs[v].d {
            u
        } else {
            v
        }
    }
    pub fn gen_lca<'a>(&'a self) -> LowestCommonAncestor<'a> {
        LowestCommonAncestor {
            seg: SegmentTree::from_vec(self.vtrace.clone(), LCAMonoid { euler: self }),
            euler: self,
        }
    }
    pub fn accumlate_etrase(&self) -> Vec<i64> {
        let mut acc = vec![0; self.etrace.len() + 1];
        let f = |i: usize, t: usize| if self.es[t].l == i { 1 } else { -1i64 };
        for i in 0..self.etrace.len() {
            let t = self.etrace[i];
            acc[i + 1] = acc[i] + f(i, t);
        }
        acc
    }
    pub fn dfs(
        &mut self,
        u: usize,
        p: usize,
        d: i64,
        ans: &mut Vec<i64>,
        acc: &mut Vec<(i64, i64)>,
        query: &Querys,
    ) {
        for &(i, x, y, coeff) in &query[u] {
            let z = d + acc[x].1 * y as i64 - acc[x].0;
            ans[i] += coeff * z;
        }
        for i in 0..self.graph.adjacency(u).len() {
            let a = self.graph.adjacency(u)[i];
            if a.to != p {
                let da = self.es[a.id].d as i64;
                let (d1, d2) = acc[self.es[a.id].c];
                acc[self.es[a.id].c] = (d1 + da, d2 + 1);
                self.dfs(a.to, u, d + da, ans, acc, query);
                acc[self.es[a.id].c] = (d1, d2);
            }
        }
    }
}
pub struct LCAMonoid<'a> {
    euler: &'a EulerTour,
}
impl<'a> Monoid for LCAMonoid<'a> {
    type T = usize;
    fn mempty(&self) -> usize {
        self.euler.graph.vsize
    }
    fn mappend(&self, u: &usize, v: &usize) -> usize {
        self.euler.ancestor(*u, *v)
    }
}
pub struct LowestCommonAncestor<'a> {
    seg: SegmentTree<LCAMonoid<'a>>,
    euler: &'a EulerTour,
}
impl<'a> LowestCommonAncestor<'a> {
    pub fn get_lca(&self, u: usize, v: usize) -> usize {
        let x = self.seg.query(self.euler.vs[u].l, self.euler.vs[v].r + 1);
        let y = self.seg.query(self.euler.vs[v].l, self.euler.vs[u].r + 1);
        self.seg.m.mappend(&x, &y)
    }
}
// }
type Querys = Vec<Vec<(usize, usize, usize, i64)>>;
fn main() {
    input! { n, q,
    abcd: [(usize1,usize1,usize1,usize); n-1],
    xyuv: [(usize1,usize,usize1,usize1); q] };
    let mut euler = EulerTour::new(n);
    for &(a, b, c, d) in &abcd {
        euler.add_edge(a, b, c, d);
    }
    euler.build();
    let lca = {
        let mut lca = vec![0; q];
        let seg = euler.gen_lca();
        for i in 0..q {
            lca[i] = seg.get_lca(xyuv[i].2, xyuv[i].3);
        }
        lca
    };
    let mut query = vec![vec![]; n];
    for i in 0..q {
        let (x, y, u, v) = xyuv[i];
        query[u].push((i, x, y, 1));
        query[v].push((i, x, y, 1));
        query[lca[i]].push((i, x, y, -2));
    }
    let mut ans = vec![0; q];
    euler.dfs(
        0,
        std::usize::MAX,
        0,
        &mut ans,
        &mut vec![(0, 0); n - 1],
        &query,
    );
    for &a in &ans {
        println!("{}", a);
    }
}


Measured memory_bytes: 73308