#include <bits/stdc++.h>
template <typename T>
void scan(T& t) {
  char c = getchar();
  T x = 1;
  t = 0;
  while (!isdigit(c)) {
    if (c == '-') x = -1;
    c = getchar();
  }
  while (isdigit(c)) t = t * 10 + c - '0', c = getchar();
  t *= x;
}
template <typename T, typename... Args>
void scan(T& t, Args&... args) {
  scan(t);
  scan(args...);
}
template <typename T>
T mul(T x, T y, T _) {
  x %= _, y %= _;
  return ((x * y - (T)(((long double)x * y + 0.5) / _) * _) % _ + _) % _;
}
using namespace std;
const int N = 500000 + 5;
int n, q, isleaf[N], L[N], R[N], id = 0, rt;
long long row[N], ans[N], d[N];
struct Nod {
  int l, r, id;
};
vector<pair<int, long long> > Graph[N];
vector<Nod> ope[N];
void adde(int u, int v, long long w) {
  Graph[u].push_back({v, w});
  Graph[v].push_back({u, w});
}
struct IntervalTree {
  long long mn[N << 2], tag[N << 2];
  int ls[N << 2], rs[N << 2], pos = 0;
  void Pushup(int p) { mn[p] = min(mn[ls[p]], mn[rs[p]]); }
  void Build(int& p, int L, int R) {
    p = ++pos;
    ls[p] = rs[p] = tag[p] = 0;
    if (L == R) {
      mn[p] = row[L];
      return;
    }
    int mid = (L + R) >> 1;
    Build(ls[p], L, mid);
    Build(rs[p], mid + 1, R);
    Pushup(p);
  }
  void Pushdown(int p, int L, int R) {
    if (tag[p]) {
      tag[ls[p]] += tag[p];
      tag[rs[p]] += tag[p];
      mn[ls[p]] += tag[p];
      mn[rs[p]] += tag[p];
      tag[p] = 0;
    }
  }
  void RangeUpdate(int p, int qL, int qR, int L, int R, long long c) {
    if (qL <= L && R <= qR) {
      mn[p] += c;
      tag[p] += c;
      return;
    }
    Pushdown(p, L, R);
    int mid = (L + R) >> 1;
    if (qL <= mid) RangeUpdate(ls[p], qL, qR, L, mid, c);
    if (qR > mid) RangeUpdate(rs[p], qL, qR, mid + 1, R, c);
    Pushup(p);
  }
  long long RangeQuery(int p, int qL, int qR, int L, int R) {
    if (qL <= L && R <= qR) return mn[p];
    Pushdown(p, L, R);
    int mid = (L + R) >> 1;
    long long ret = (long long)(1e18);
    if (qL <= mid) ret = min(ret, RangeQuery(ls[p], qL, qR, L, mid));
    if (qR > mid) ret = min(ret, RangeQuery(rs[p], qL, qR, mid + 1, R));
    return ret;
  }
} T;
void dfs(int u, int pre) {
  int child = 0;
  row[++id] = u;
  L[u] = id;
  for (int i = 0; i < Graph[u].size(); i++) {
    int v = Graph[u][i].first;
    long long w = Graph[u][i].second;
    if (pre == v) continue;
    ++child;
    d[v] = d[u] + w;
    dfs(v, u);
  }
  R[u] = id;
  if (!child) isleaf[u] = 1;
}
void dfs2(int u, int pre, long long w) {
  T.RangeUpdate(rt, 1, n, 1, n, w);
  T.RangeUpdate(rt, L[u], R[u], 1, n, -2 * w);
  for (int i = 0; i < ope[u].size(); i++) {
    int l = ope[u][i].l, r = ope[u][i].r, id = ope[u][i].id;
    ans[id] = T.RangeQuery(rt, l, r, 1, n);
  }
  for (int i = 0; i < Graph[u].size(); i++) {
    int v = Graph[u][i].first;
    long long ww = Graph[u][i].second;
    if (v == pre) continue;
    dfs2(v, u, ww);
  }
  T.RangeUpdate(rt, 1, n, 1, n, -w);
  T.RangeUpdate(rt, L[u], R[u], 1, n, 2 * w);
}
int main() {
  scan(n, q);
  int p;
  long long w;
  for (int i = 2; i <= n; i++) scan(p, w), adde(p, i, w);
  for (int i = 1; i <= n; i++) sort(Graph[i].begin(), Graph[i].end());
  dfs(1, 0);
  for (int i = 1; i <= n; i++) {
    if (!isleaf[row[i]])
      row[i] = (long long)(1e18);
    else
      row[i] = d[row[i]];
  }
  T.Build(rt, 1, n);
  for (int i = 1; i <= q; i++) {
    int v, l, r, id;
    scan(v, l, r);
    id = i;
    ope[v].push_back((Nod){l, r, id});
  }
  dfs2(1, 0, 0);
  for (int i = 1; i <= q; i++) {
    printf("%lld\n", ans[i]);
  }
  return 0;
}
