#include <bits/stdc++.h>
using namespace std;
template <class X, class Y>
bool minimize(X &x, const Y &y) {
  X eps = 1e-9;
  if (x > y + eps) {
    x = y;
    return true;
  } else
    return false;
}
template <class X, class Y>
bool maximize(X &x, const Y &y) {
  X eps = 1e-9;
  if (x + eps < y) {
    x = y;
    return true;
  } else
    return false;
}
template <class T>
T Abs(const T &x) {
  return (x < 0 ? -x : x);
}
const long long INF = (long long)1e18 + 7ll;
class SegmentTree {
 private:
  vector<long long> tree, lazy;
  int n;
  void pushDown(int i) {
    for (int j = (2 * i), _b = (2 * i + 1); j <= _b; j++) {
      tree[j] += lazy[i];
      lazy[j] += lazy[i];
    }
    lazy[i] = 0;
  }
  void update(int i, int l, int r, int u, int v, long long c) {
    if (l > v || r < u || l > r || v < u) return;
    if (u <= l && r <= v) {
      tree[i] += c;
      lazy[i] += c;
      return;
    }
    pushDown(i);
    int m = (l + r) >> 1;
    update(2 * i, l, m, u, v, c);
    update(2 * i + 1, m + 1, r, u, v, c);
    tree[i] = min(tree[2 * i], tree[2 * i + 1]);
  }
  long long getMin(int i, int l, int r, int u, int v) {
    if (l > v || r < u || l > r || v < u) return INF;
    if (u <= l && r <= v) return tree[i];
    pushDown(i);
    int m = (l + r) >> 1;
    long long L = getMin(2 * i, l, m, u, v);
    long long R = getMin(2 * i + 1, m + 1, r, u, v);
    return min(L, R);
  }

 public:
  SegmentTree(int n = 0) {
    this->n = n;
    if (n > 0) {
      tree.assign(4 * n + 7, 0);
      lazy.assign(4 * n + 7, 0);
    }
  }
  void update(int l, int r, long long c) { update(1, 1, n, l, r, c); }
  long long getMin(int l, int r) { return getMin(1, 1, n, l, r); }
};
int numNode, numQuery, cnt;
vector<pair<int, int>> children[500500];
pair<int, int> queries[500500];
int sta[500500], fin[500500], firstLeaf[500500], lastLeaf[500500];
long long dist[500500];
int leaves[500500], numLeaf;
vector<int> queryAt[500500];
long long answer[500500];
SegmentTree myit;
void init(void) {
  scanf("%d%d", &numNode, &numQuery);
  for (int i = (2), _b = (numNode); i <= _b; i++) {
    int p, c;
    scanf("%d%d", &p, &c);
    children[p].push_back(make_pair(i, c));
  }
  for (int i = (1), _b = (numQuery); i <= _b; i++) {
    int v, l, r;
    scanf("%d%d%d", &v, &l, &r);
    queries[i] = make_pair(l, r);
    queryAt[v].push_back(i);
  }
}
void prepareDFS(int u) {
  sta[u] = ++cnt;
  firstLeaf[u] = numNode + 1;
  if (children[u].empty()) {
    leaves[++numLeaf] = u;
    firstLeaf[u] = lastLeaf[u] = numLeaf;
  } else {
    for (__typeof((children[u]).begin()) it = (children[u]).begin();
         it != (children[u]).end(); it++) {
      int v = it->first;
      dist[v] = dist[u] + it->second;
      prepareDFS(v);
      minimize(firstLeaf[u], firstLeaf[v]);
      maximize(lastLeaf[u], lastLeaf[v]);
    }
  }
  fin[u] = cnt;
}
void answerDFS(int u) {
  for (__typeof((queryAt[u]).begin()) it = (queryAt[u]).begin();
       it != (queryAt[u]).end(); it++) {
    int l = queries[*it].first;
    int r = queries[*it].second;
    int id = lower_bound(leaves + 1, leaves + numLeaf + 1, l) - leaves;
    int jd = upper_bound(leaves + 1, leaves + numLeaf + 1, r) - leaves - 1;
    assert(id <= jd);
    answer[*it] = myit.getMin(id, jd);
  }
  for (__typeof((children[u]).begin()) it = (children[u]).begin();
       it != (children[u]).end(); it++) {
    int v = it->first;
    myit.update(firstLeaf[v], lastLeaf[v], -it->second);
    myit.update(1, firstLeaf[v] - 1, it->second);
    myit.update(lastLeaf[v] + 1, numLeaf, it->second);
    answerDFS(v);
    myit.update(firstLeaf[v], lastLeaf[v], it->second);
    myit.update(1, firstLeaf[v] - 1, -it->second);
    myit.update(lastLeaf[v] + 1, numLeaf, -it->second);
  }
}
void process(void) {
  prepareDFS(1);
  myit = SegmentTree(numLeaf);
  for (int i = (1), _b = (numLeaf); i <= _b; i++)
    myit.update(i, i, dist[leaves[i]]);
  answerDFS(1);
  for (int i = (1), _b = (numQuery); i <= _b; i++) cout << answer[i] << "\n";
}
int main(void) {
  init();
  process();
  return 0;
}
