#include <bits/stdc++.h>
using namespace std;
template <typename T1, typename T2>
istream &operator>>(istream &in, pair<T1, T2> &a) {
  in >> a.first >> a.second;
  return in;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &out, pair<T1, T2> a) {
  out << a.first << " " << a.second;
  return out;
}
template <typename T, typename T1>
T maxs(T &a, T1 b) {
  if (b > a) a = b;
  return a;
}
template <typename T, typename T1>
T mins(T &a, T1 b) {
  if (b < a) a = b;
  return a;
}
struct node {
  long long a = 0;
  node(long long val = 0) { a = val; }
  void merge(node &n1, node &n2) { this->a = min(n1.a, n2.a); }
} nul;
template <typename node>
struct segtree {
  node *t;
  void resize(long long n) { t = new node[4 * n]; }
  void build(int32_t v, int32_t start, int32_t end, vector<long long> &arr) {
    if (start == end) {
      t[v].a = arr[start];
    } else {
      int32_t m = (start + end) / 2;
      build(2 * v, start, m, arr);
      build(2 * v + 1, m + 1, end, arr);
      t[v].merge(t[2 * v], t[2 * v + 1]);
    }
  }
  node query(int32_t v, int32_t l, int32_t r, int32_t tl, int32_t tr) {
    if (tr < l || tl > r) return nul;
    if (l <= tl && tr <= r) {
      return t[v];
    }
    long long mid = (tl + tr) / 2;
    node a = query(2 * v, l, r, tl, mid);
    node b = query(2 * v + 1, l, r, mid + 1, tr);
    node ans;
    ans.merge(a, b);
    return ans;
  }

 public:
  node query(int32_t l, int32_t r, int32_t tl, int32_t tr) {
    return query(1, l, r, tl, tr);
  }
};
const long long maxn = 500005;
set<pair<long long, long long>> g[maxn];
int32_t p[maxn];
int32_t b_p[maxn][21];
long long level[maxn];
int32_t lvl2[maxn];
vector<long long> leaves;
void dfs(int32_t n, int32_t e, long long l) {
  p[n] = e;
  level[n] = l;
  if (g[n].size() == 1) leaves.push_back(n);
  for (auto i : g[n]) {
    if (i.first != e) {
      lvl2[i.first] = lvl2[n] + 1;
      long long w = i.second;
      dfs(i.first, n, l + w);
    }
  }
  return;
}
void lift(int32_t n) {
  for (long long i = 0; i <= 20; i++) {
    for (long long j = 1; j <= n; j++) {
      if (i == 0)
        b_p[j][i] = p[j];
      else
        b_p[j][i] = b_p[b_p[j][i - 1]][i - 1];
    }
  }
  return;
}
int32_t lca(int32_t u, int32_t v) {
  if (lvl2[v] < lvl2[u]) u = v + u - (v = u);
  int32_t diff = lvl2[u] - lvl2[v];
  for (long long i = 20; i >= 0; i--) {
    if (lvl2[v] - lvl2[u] >= (1 << i)) {
      v = b_p[v][i];
    }
  }
  if (v == u) {
    return u;
  }
  int32_t k = ceil(log2(lvl2[u]));
  while (k >= 0) {
    if (b_p[u][k] != b_p[v][k]) {
      u = b_p[u][k];
      v = b_p[v][k];
    }
    k--;
  }
  return p[u];
}
long long d(int32_t u, int32_t v) {
  return level[u] + level[v] - 2 * level[lca(u, v)];
}
int32_t ctree[maxn];
int32_t sz[maxn];
int32_t temp = 0;
vector<int32_t> cen[maxn];
void dfs1(long long u, long long par) {
  sz[u] = 1;
  temp++;
  for (auto i : g[u]) {
    if (i.first != par) {
      dfs1(i.first, u);
      sz[u] += sz[i.first];
    }
  }
}
long long dfs2(long long u, long long par) {
  for (auto i : g[u]) {
    if (i.first != par && sz[i.first] > temp / 2) {
      return dfs2(i.first, u);
    }
  }
  return u;
}
void decompose(long long u, long long par) {
  temp = 0;
  dfs1(u, u);
  long long centroid = dfs2(u, u);
  if (par <= 0) par = centroid;
  ctree[centroid] = par;
  for (auto i : g[centroid]) {
    g[i.first].erase({centroid, i.second});
    decompose(i.first, centroid);
  }
  g[centroid].clear();
}
unordered_map<long long, segtree<node>> seg;
void process(int32_t n) {
  for (auto i : leaves) {
    int32_t first = i;
    while (1) {
      cen[first].push_back(i);
      if (first == ctree[first]) break;
      first = ctree[first];
    }
  }
  for (int32_t i = 1; i <= n; i++) {
    if (cen[i].empty()) continue;
    vector<long long> temp;
    sort(cen[i].begin(), cen[i].end());
    for (auto j : cen[i]) temp.push_back(d(i, j));
    seg[i].resize((long long)temp.size());
    seg[i].build(1, 0, (long long)temp.size() - 1, temp);
  }
}
long long query(int32_t first, int32_t l, int32_t r) {
  int32_t u = first;
  long long mi = 1e18;
  while (1) {
    long long val = d(first, u);
    if (cen[u].empty() || cen[u].front() > r || cen[u].back() < l) {
      if (u == ctree[u] || ctree[u] == 0) break;
      u = ctree[u];
    } else {
      int32_t l2 =
          lower_bound(cen[u].begin(), cen[u].end(), l) - cen[u].begin();
      int32_t r2 =
          upper_bound(cen[u].begin(), cen[u].end(), r) - cen[u].begin();
      r2--;
      mins(mi, val + seg[u].query(l2, r2, 0, (long long)cen[u].size() - 1).a);
      if (u == ctree[u] || ctree[u] == 0) break;
      u = ctree[u];
    }
  }
  return mi;
}
int solve() {
  int n, q;
  cin >> n >> q;
  for (int i = 0; i < n - 1; i++) {
    int p, w;
    cin >> p >> w;
    g[i + 2].insert({p, w});
    g[p].insert({i + 2, w});
  }
  dfs(1, 0, 0);
  lift(n);
  decompose(1, -1);
  process(n);
  for (int i = 1; i <= q; i++) {
    int v, l, r;
    cin >> v >> l >> r;
    cout << query(v, l, r) << "\n";
  }
  return 0;
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  nul.a = 1e18;
  int t = 1;
  while (t--) {
    solve();
  }
  return 0;
}
