#include <bits/stdc++.h>

using namespace std;
using ll = long long;

struct SegTree {
  struct Node {
    int x;
    int push = -1;
  };
  Node merge(Node n1, Node n2) {
    return {n1.x + n2.x, -1};
  }
  vector<Node> t;
  void push(int v, int l, int r) {
    if (t[v].push == -1) return;
    t[v].x = t[v].push * (r - l);
    t[2 * v + 1].push = t[v].push;
    t[2 * v + 2].push = t[v].push;
    t[v].push = -1;
  }
  void upd(int v, int l, int r, int ql, int qr, int x) {
    push(v, l, r);
    if (l >= ql && r <= qr) {
      t[v].push = x;
      return;
    }
    if (l >= qr || r  <= ql) return;
    int m = (l + r) / 2;
    upd(2 * v + 1, l, m, ql, qr, x);
    upd(2 * v + 2, m, r, ql, qr, x);
  }

  Node get(int v, int l, int r, int ql, int qr) {
    push(v, l, r);
    if (l >= ql && r <= qr) {
      return t[v];
    }
    if (l >= qr || r  <= ql) return {0, -1};
    int m = (l + r) / 2;
    return merge(get(2 * v + 1, l, m, ql, qr), get(2 * v + 1, m, r, ql, qr));
  }
};


vector<vector<pair<ll, ll>>> g;
vector<ll> col; // mask
const ll LG = 21;
void dfs1(ll v, ll c, ll p) {
  col[v] = c;
  for (auto [u, h] : g[v]) {
    if (u == p) continue;
    dfs1(u, c ^ h, v);
  }
}

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) {
  g.resize(n);
  col.resize(n);
  for (ll i = 0; i < n - 1; i++) {
    g[v[i]].emplace_back(u[i], h[i]);
    g[u[i]].emplace_back(v[i], h[i]);
  }
  dfs1(0, 0, -1);
  vector<ll> cnt(LG, 0); // col[j] = 1
  ll ans = 0;
  ll cntOpen = 0;
  vector<ll> ret(q);
  vector<bool> open(n, 0);
  vector<SegTree> a(LG);
  for (int i = 0; i < LG; i++) {
    a[i].t.resize(4 * n, {0, -1});
    for (int j = 0; j < n; j++) {
      if ((1 << i) & col[j]) {
        a[i].upd(0, 0, n, j, j + 1, 1);
      }
    }
  }
  for (ll i = 0; i < q; i++) {
    for (ll k = 0; k < LG; k++) {
      if (t[i] == 1) {
        int cntGood = a[k].get(0, 0, n, l[i], r[i] + 1).x;
        int cntOth = r[i] - l[i] + 1 - cntGood;
        int cntGoodOut = cnt[k];
        int cntOthOut = cntOpen - cnt[k];
        ans += (cntGood * cntOth + cntGood * cntOthOut + cntOth * cntGoodOut) * (1 << k);
        cnt[k] += cntGood;
        cntOpen += (r[i] - l[i] + 1);

      } else {
        int cntGood = a[k].get(0, 0, n, l[i], r[i] + 1).x;
        int cntOth = r[i] - l[i] + 1 - cntGood;
        int cntGoodOut = cnt[k];
        int cntOthOut = cntOpen - cnt[k];
        ans -= (cntGood * cntOth + cntGood * cntOthOut + cntOth * cntGoodOut) * (1 << k);
        cnt[k] -= cntGood;
        cntOpen -= (r[i] - l[i] + 1);
      }
    }
    ret[i] = ans;
  }
  return ret;
}