#ifdef EVAL
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx,avx2")
#include <bits/stdc++.h>
#define debug(x)
#else
#define debug(x) cout << __LINE__ << ": " << (#x) << " = " << x << endl;
#endif
#include <iostream>
#include <vector>
#include <algorithm>
#include "happy.h"
using namespace std;
using ll = long long;


const int MAX_N = 3e5 + 10;
vector<vector<pair<int, int>>> g(MAX_N);
//vector<vector<int>> binup(MAX_LOG, vector<int>(MAX_N));
vector<int> values(MAX_N); // tin(MAX_N), tout(MAX_N), d(MAX_N);
int timer = 0;


void dfs(int v, int p, int val) {
    //binup[0][v] = p;
    values[v] = val;
    //d[v] = d[p] + 1;
    /*for (int k = 1; k < MAX_LOG; k++) {
        binup[k][v] = binup[k - 1][ binup[k - 1][v] ];
    }*/

    //tin[v] = ++timer;
    for (auto [u, h] : g[v]) {
        if (u == p) continue;
        dfs(u, v, h ^ val);
    }
    //tout[v] = timer;
}


/*bool isParent(int u, int v) {
    return tin[u] <= tin[v] && tout[v] <= tout[u];
}


int lca(int u, int v) {
    if (isParent(u, v)) return u;
    if (isParent(v, u)) return v;
    if (d[u] > d[v]) swap(u, v);

    for (int k = MAX_LOG - 1; k >= 0; k--) {
        if (d[v] - d[u] >= (1 << k)) {
            v = binup[k][v];
        }
    }

    for (int k = MAX_LOG - 1; k >= 0; k--) {
        if (binup[k][v] != binup[k][u]) {
            v = binup[k][v];
            u = binup[k][u];
        }
    }
    return binup[0][v];
}*/

// : D
// solving bit by bit in offline!!
// then memory will be ok
// funny

struct Val {
    bool start, end;
    array<array<int, 3>, 2> pref, suf; // 0 - can both, 1 - can start, 2 - can end
    int val;
    ll ans;

    Val merge(const Val &other) const {
        auto npref = pref;
        auto nsuf = other.suf;

        for (int i = 0; i < 3; i++) npref[0][i] += other.pref[0 ^ val][i];
        for (int i = 0; i < 3; i++) npref[1][i] += other.pref[1 ^ val][i];

        for (int i = 0; i < 3; i++) nsuf[0][i] += suf[0 ^ other.val][i];
        for (int i = 0; i < 3; i++) nsuf[1][i] += suf[1 ^ other.val][i];

        return {
            start, end,
            npref,
            nsuf,
            val ^ other.val,
            ans + other.ans + (suf[0][0] + suf[0][1]) * (other.pref[1][0] + other.pref[1][2]) + (suf[1][0] + suf[1][1]) * (other.pref[0][0] + other.pref[0][2])
        };
    }
};


const Val NE = {false, false, {{0, 0, 0}}, {{0, 0, 0}}, 0, 0};


struct Node {
    Val current, original;
};


struct Segtree {
    vector<Node> t;
    vector<int> op;

    Segtree(int n) {
        t.resize(4 * n + 10);
        op.resize(4 * n + 10, -1);
    }

    Segtree(vector<int> &a) {
        t.resize(4 * a.size() + 10);
        op.resize(4 * a.size() + 10, -1);
        op.assign(4 * a.size() + 10, -1);
        build(0, 0, a.size(), a);
    }

    void build(int v, int l, int r, vector<int> &a) {
        op[v] = -1;
        if (l + 1 == r) {
            int val = a[l];

            t[v].current = NE;
            auto &vl = t[v].original;
            vl = NE;

            vl.start = true;
            vl.end = true;
            vl.ans = 0;
            for (int x = 0; x <= 1; x++) {
                for (int j = 0; j <= 2; j++) {
                    vl.suf[x][j] = 0;
                    vl.pref[x][j] = 0;
                }
            }

            if (vl.start && vl.end) {
                vl.ans = val;
                vl.pref[val][0] = 1;
                vl.suf[val][0] = 1;
            } else if (vl.start) {
                vl.pref[val][1] = 1;
                vl.suf[val][1] = 1;
            } else if (vl.end) {
                vl.pref[val][2] = 1;
                vl.suf[val][2] = 1;
            }

            t[v].current.val = val;
            t[v].original.val = val;
            return;
        }

        int mid = (l + r) / 2;
        build(2 * v + 1, l, mid, a);
        build(2 * v + 2, mid, r, a);
        t[v].current = t[2 * v + 1].current
                .merge(t[2 * v + 2].current);
        t[v].original = t[2 * v + 1].original
                 .merge(t[2 * v + 2].original);
    }

    void push(int v, int l, int r) {
        if (op[v] == -1 || l + 1 == r) return;
        if (op[v] == 1) {
            t[2 * v + 1].current = t[2 * v + 1].original;
            t[2 * v + 2].current = t[2 * v + 2].original;
        } else {
            t[2 * v + 1].current = NE;
            t[2 * v + 2].current = NE;
        }
        op[2 * v + 1] = op[v];
        op[2 * v + 2] = op[v];
        op[v] = -1;
    }

    Val get(int v, int l, int r, int lq, int rq) {
        if (rq <= l || r <= lq) {
            return NE;
        }

        if (lq <= l && r <= rq) {
            return t[v].current;
        }

        int mid = (l + r) / 2;
        push(v, l, r);
        return get(2 * v + 1, l, mid, lq, rq)
        .merge(get(2 * v + 2, mid, r, lq, rq));
    }

    void update(int v, int l, int r, int i, int nstart, int nend) {
        if (i < l || r <= i) {
            return;
        }

        if (l == i && r == i + 1) {
            auto &vl = t[v].current;
            int val = vl.val;
            if (nend != -1) {
                vl.end = nend;
            }
            if (nstart != -1) {
                vl.start = nstart;
            }
            
            vl.ans = 0;
            for (int x = 0; x <= 1; x++) {
                for (int j = 0; j <= 2; j++) {
                    vl.suf[x][j] = 0;
                    vl.pref[x][j] = 0;
                }
            }

            if (vl.start && vl.end) {
                vl.ans = val;
                vl.pref[val][0] = 1;
                vl.suf[val][0] = 1;
            } else if (vl.start) {
                vl.pref[val][1] = 1;
                vl.suf[val][1] = 1;
            } else if (vl.end) {
                vl.pref[val][2] = 1;
                vl.suf[val][2] = 1;
            }

            return; 
        }

        int mid = (l + r) / 2;
        push(v, l, r);
        update(2 * v + 1, l, mid, i, nstart, nend);
        update(2 * v + 2, mid, r, i, nstart, nend);
        t[v].current = t[2 * v + 1].current
                .merge(t[2 * v + 2].current);
    }

    void updat(int v, int l, int r, int lq, int rq, int nw) {
        if (rq <= l || r <= lq) {
            return;
        }

        if (lq <= l && r <= rq) {
            if (nw == 1) {
                t[v].current = t[v].original;
            } else {
                t[v].current = NE;
            }
            op[v] = nw;
            return;
        }

        int mid = (l + r) / 2;
        push(v, l, r);
        updat(2 * v + 1, l, mid, lq, rq, nw);
        updat(2 * v + 2, mid, r, lq, rq, nw);
        t[v].current = t[2 * v + 1].current
                .merge(t[2 * v + 2].current);
    }
};


Segtree seg(MAX_N);


vector<ll> happy(int N, int Q, std::vector<int> u, std::vector<int> v, std::vector<int> h, std::vector<int> t, std::vector<int> l, std::vector<int> r) {
    vector<ll> a(N);

    for (int i = 0; i < u.size(); i++) {
        int U = u[i];
        int V = v[i];
        int H = h[i];
        g[U].push_back({V, H});
        g[V].push_back({U, H});
    }
    dfs(0, 0, 0);

    for (int i = 0; i < N; i++) {
        int next = i + 1;
        a[i] = values[i] ^ values[next];
    }

    vector<ll> answers(Q);
    for (int k = 0; k < 20; k++) {
        vector<bool> begin(N, false), end(N, false);
        vector<int> aa(N);
        int sum = 0;
        for (int i = 0; i < N; i++) {
            if (a[i] & (1 << k)) aa[i] = 1;
            sum += aa[i];
        }
        if (sum == 0) continue;
        seg.build(0, 0, aa.size(), aa);
        for (int i = 0; i < Q; i++) {
            int L = l[i];
            int R = r[i];
            int T = t[i];

            T = T % 2;

            seg.updat(0, 0, N, L, R, T);
            //for (int v = L; v < R; v++) {
            //    seg.update(0, 0, N, v, T, T);
            //}
            seg.update(0, 0, N, R, T, -1);
            if (L > 0) seg.update(0, 0, N, L - 1, -1, T);
            debug(seg.t[0].current.ans);

            ll res = seg.t[0].current.ans;
            answers[i] += res * (ll) (1ll << (ll) k);
        }
    }

    return answers;
}


#ifndef EVAL
extern vector <long long int> happy (int N, int Q, vector <int> u, vector <int> v, vector <int> h, vector <int> t, vector <int> l, vector <int> r);
int main () {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n,q;
    cin >> n >> q ;
    vector <int> u(n-1),v(n-1),h(n-1);
    for (int i=0; i<n-1; i++) {
        cin >> u[i] >> v[i] >> h[i] ;
    }
    vector <int> t(q),l(q),r(q);
    for (int i=0; i<q; i++) {
        cin >> t[i] >> l[i] >> r[i] ;
    }
    for (auto sum : happy(n,q,u,v,h,t,l,r)) {
        cout << sum << "\n";
    }
    return 0;
}
#endif
