#include <bits/stdc++.h>
using namespace std;
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  long long n, q;
  cin >> n >> q;
  vector<long long> parents((size_t)n, -1);
  vector<long long> weights((size_t)n, 0);
  vector<vector<long long>> children((size_t)n);
  for (long long i = 1; i < n; i++) {
    cin >> parents[i] >> weights[i];
    parents[i]--;
    children[parents[i]].push_back(i);
  }
  long long m = 1 << 18;
  vector<long long> tree_add((size_t)m, 0),
      tree_min((size_t)m, (long long)1e16);
  auto tree_propagate = [&](long long tree_v, long long tree_l,
                            long long tree_r) {
    if (tree_l == tree_r) {
      tree_min[tree_v] += tree_add[tree_v];
      tree_add[tree_v] = 0;
    } else {
      tree_add[tree_v * 2 + 0] += tree_add[tree_v];
      tree_add[tree_v * 2 + 1] += tree_add[tree_v];
      tree_add[tree_v] = 0;
      tree_min[tree_v] =
          min(tree_min[tree_v * 2 + 0] + tree_add[tree_v * 2 + 0],
              tree_min[tree_v * 2 + 1] + tree_add[tree_v * 2 + 1]);
    }
  };
  function<void(long long, long long, long long, long long, long long,
                long long)>
      tree_update = [&](long long tree_v, long long tree_l, long long tree_r,
                        long long l, long long r, long long x) {
        if (l > r) {
          return;
        }
        tree_propagate(tree_v, tree_l, tree_r);
        if (tree_l >= l && tree_r <= r) {
          tree_add[tree_v] += x;
        } else if (tree_l <= r && tree_r >= l) {
          tree_update(tree_v * 2 + 0, tree_l, tree_l + (tree_r - tree_l) / 2, l,
                      r, x);
          tree_update(tree_v * 2 + 1, tree_r - (tree_r - tree_l) / 2, tree_r, l,
                      r, x);
        }
        tree_propagate(tree_v, tree_l, tree_r);
      };
  function<long long(long long, long long, long long, long long, long long)>
      tree_query = [&](long long tree_v, long long tree_l, long long tree_r,
                       long long l, long long r) {
        tree_propagate(tree_v, tree_l, tree_r);
        if (tree_l >= l && tree_r <= r) {
          return tree_min[tree_v];
        } else if (tree_l <= r && tree_r >= l) {
          return min(tree_query(tree_v * 2 + 0, tree_l,
                                tree_l + (tree_r - tree_l) / 2, l, r),
                     tree_query(tree_v * 2 + 1, tree_r - (tree_r - tree_l) / 2,
                                tree_r, l, r));
        }
        return numeric_limits<long long>::max();
      };
  vector<long long> maximums((size_t)n);
  iota(maximums.begin(), maximums.end(), (long long)0);
  function<void(long long, long long)> visit_first = [&](long long u,
                                                         long long i) {
    if (children[u].empty()) {
      tree_update(1, 0, m / 2 - 1, u, maximums[u], i - (long long)1e16);
    } else {
      for (long long v : children[u]) {
        visit_first(v, i + weights[v]);
        maximums[u] = max(maximums[u], maximums[v]);
      }
    }
  };
  visit_first(0, 0);
  vector<vector<tuple<long long, long long, long long>>> queries((size_t)n);
  for (long long i = 0; i < q; i++) {
    long long v, l, r;
    cin >> v >> l >> r;
    v--, l--, r--;
    queries[v].emplace_back(i, l, r);
  }
  vector<long long> answers((size_t)q);
  function<void(long long)> visit_second = [&](long long u) {
    tree_update(1, 0, m / 2 - 1, 0, u - 1, weights[u]);
    tree_update(1, 0, m / 2 - 1, u, maximums[u], -weights[u]);
    tree_update(1, 0, m / 2 - 1, maximums[u] + 1, n - 1, weights[u]);
    for (auto [i, l, r] : queries[u]) {
      answers[i] = tree_query(1, 0, m / 2 - 1, l, r);
    }
    for (long long v : children[u]) {
      visit_second(v);
    }
    tree_update(1, 0, m / 2 - 1, 0, u - 1, -weights[u]);
    tree_update(1, 0, m / 2 - 1, u, maximums[u], weights[u]);
    tree_update(1, 0, m / 2 - 1, maximums[u] + 1, n - 1, -weights[u]);
  };
  visit_second(0);
  for (long long i : answers) {
    cout << i << "\n";
  }
  return 0;
}
