#include <bits/stdc++.h>
using namespace std;
const int M = 1 << 20;
const long long INF = 1e15;
struct Node {
  int l, r;
  long long val, add;
  Node(int _l, int _r) : l(_l), r(_r), val(0), add(0){};
  Node(){};
  void Add(long long x) {
    val += x;
    add += x;
  }
};
Node tree[2 * M];
void push(int v) {
  tree[2 * v].Add(tree[v].add);
  tree[2 * v + 1].Add(tree[v].add);
  tree[v].add = 0;
}
void build() {
  for (int i = 0; i < M; ++i) tree[M + i] = Node(i, i + 1);
  for (int i = M - 1; i > 0; --i)
    tree[i] = Node(tree[2 * i].l, tree[2 * i + 1].r);
}
void addOnSegment(int v, int l, int r, long long add) {
  if (r <= tree[v].l || tree[v].r <= l) return;
  if (l <= tree[v].l && tree[v].r <= r) {
    tree[v].Add(add);
    return;
  }
  push(v);
  addOnSegment(2 * v, l, r, add);
  addOnSegment(2 * v + 1, l, r, add);
  tree[v].val = min(tree[2 * v].val, tree[2 * v + 1].val);
}
long long getMin(int v, int l, int r) {
  if (r <= tree[v].l || tree[v].r <= l) return INF;
  if (l <= tree[v].l && tree[v].r <= r) return tree[v].val;
  push(v);
  long long ansL = getMin(2 * v, l, r);
  long long ansR = getMin(2 * v + 1, l, r);
  return min(ansL, ansR);
}
const int N = 5e5;
vector<pair<int, long long> > g[N];
int id[N], posId[N];
int posLeavs[N];
long long a[N];
pair<int, int> ed[N];
void dfs(int v) {
  static int ID = 0;
  id[v] = ID++;
  posId[id[v]] = v;
  if (v && g[v].empty())
    ed[v] = {id[v], id[v]};
  else
    ed[v] = {N, -1};
  for (auto pr : g[v]) {
    int u = pr.first;
    a[u] = a[v] + pr.second;
    dfs(u);
    ed[v].first = min(ed[v].first, ed[u].first);
    ed[v].second = max(ed[v].second, ed[u].second);
  }
}
struct Query {
  int id;
  int l, r;
  long long ans;
  Query(int _id, int _l, int _r) : id(_id), l(_l), r(_r){};
  Query(){};
};
Query qry[N];
vector<int> qinv[N];
int szLeavs;
void add(int u, long long w) {
  addOnSegment(1, ed[u].first, ed[u].second + 1, w);
  addOnSegment(1, 0, ed[u].first, -w);
  addOnSegment(1, ed[u].second + 1, szLeavs, -w);
}
void dfsQ(int v) {
  for (int i : qinv[v]) qry[i].ans = getMin(1, qry[i].l, qry[i].r + 1);
  for (auto pr : g[v]) {
    int u = pr.first;
    long long w = pr.second;
    add(u, -w);
    dfsQ(u);
    add(u, w);
  }
}
int main() {
  int n, q;
  scanf("%d%d", &n, &q);
  for (int i = 1; i < n; ++i) {
    static int p;
    static long long w;
    scanf("%d%lld", &p, &w);
    --p;
    g[p].push_back({i, w});
  }
  dfs(0);
  vector<int> leavs;
  for (int v = 1; v < n; ++v)
    if (g[v].empty()) leavs.push_back(id[v]);
  sort(leavs.begin(), leavs.end());
  szLeavs = (int)leavs.size();
  for (int i = 0; i < (int)szLeavs; ++i) posLeavs[leavs[i]] = i;
  for (int v = 0; v < n; ++v)
    ed[v] = {posLeavs[ed[v].first], posLeavs[ed[v].second]};
  for (int i = 0; i < q; ++i) {
    static int v, l, r;
    scanf("%d%d%d", &v, &l, &r);
    --v;
    --l;
    --r;
    l = lower_bound(leavs.begin(), leavs.end(), l) - leavs.begin();
    static int nr;
    nr = lower_bound(leavs.begin(), leavs.end(), r) - leavs.begin();
    if (nr != szLeavs && leavs[nr] != r) --nr;
    r = nr;
    qry[i] = Query(i, l, r);
    qinv[v].push_back(i);
  }
  build();
  for (int i = 0; i < szLeavs; ++i)
    addOnSegment(1, i, i + 1, a[posId[leavs[i]]]);
  dfsQ(0);
  for (int i = 0; i < q; ++i) printf("%lld\n", qry[i].ans);
}
