#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e6 + 5;
long long magic_const = 3e18;
const int MAX_L = 3;
class segment_tree {
  int n;
  vector<long long> val;
  vector<long long> pushes;
  int l, r;
  long long ans, adding_value;
  void push(int v, bool is_leaf) {
    val[v] += pushes[v];
    if (!is_leaf) {
      pushes[v << 1] += pushes[v];
      pushes[(v << 1) + 1] += pushes[v];
    }
    pushes[v] = 0;
  }
  void update(int v) {
    int lp = v << 1;
    int rp = lp + 1;
    val[v] = min(val[lp] + pushes[lp], val[rp] + pushes[rp]);
  }
  void build(vector<long long>& a, int v, int lb, int rb) {
    if (lb == rb) {
      val[v] = a[lb];
      return;
    }
    int midt = (lb + rb) / 2;
    int lv = v << 1;
    int rv = lv + 1;
    build(a, lv, lb, midt);
    build(a, rv, midt + 1, rb);
    update(v);
  }
  void count(int v, int lb, int rb) {
    push(v, lb == rb);
    if (lb >= l && rb <= r) {
      ans = min(ans, val[v]);
    } else {
      int midt = (lb + rb) / 2;
      int lv = v << 1;
      int rv = lv + 1;
      if (midt >= l && lb <= r) count(lv, lb, midt);
      if (midt + 1 <= r && rb >= l) count(rv, midt + 1, rb);
    }
  }
  void add(int v, int lb, int rb) {
    push(v, lb == rb);
    if (lb >= l && rb <= r) {
      pushes[v] += adding_value;
    } else {
      int midt = (lb + rb) / 2;
      int lv = v << 1;
      int rv = lv + 1;
      if (midt >= l && lb <= r) add(lv, lb, midt);
      if (midt + 1 <= r && rb >= l) add(rv, midt + 1, rb);
      update(v);
    }
  }

 public:
  segment_tree(vector<long long>& a) {
    n = a.size();
    if (n < 10) {
      val.resize(n * 4, magic_const);
      pushes.resize(n * 4);
    } else {
      val.resize(n * 4, magic_const);
      pushes.resize(n * 4);
    }
    build(a, 1, 0, n - 1);
  }
  long long get_answer(int l, int r) {
    this->l = l;
    this->r = r;
    this->ans = magic_const;
    count(1, 0, n - 1);
    return this->ans;
  }
  void add_on_segment(int l, int r, long long value) {
    this->l = l;
    this->r = r;
    this->adding_value = value;
    add(1, 0, n - 1);
  }
};
int n, m;
vector<vector<int>> graph;
vector<vector<int>> cost;
vector<int> pr;
vector<int> pr_cost;
vector<int> h;
vector<pair<pair<int, int>, pair<int, int>>> queries;
vector<int> tin;
vector<int> tout;
vector<int> leafs;
vector<long long> used;
int t = 0;
void dfs(int v, int new_h) {
  tin[v] = t++;
  h[v] = new_h;
  if (graph[v].size() <= 1) leafs.push_back(v);
  for (int i = 0; i < graph[v].size(); i++) {
    int new_v = graph[v][i];
    if (h[new_v] == -1) {
      pr[new_v] = v;
      pr_cost[new_v] = cost[v][i];
      dfs(new_v, new_h + 1);
    }
  }
  tout[v] = t;
}
void dfs_2(int v, long long cnt) {
  used[v] = cnt;
  for (int i = 0; i < graph[v].size(); i++) {
    int new_v = graph[v][i];
    if (used[new_v] == -1) {
      dfs_2(new_v, cnt + cost[v][i]);
    }
  }
}
const bool cmp(const pair<pair<int, int>, pair<int, int>>& first,
               const pair<pair<int, int>, pair<int, int>>& second) {
  if (tin[first.first.first] != tin[second.first.first])
    return tin[first.first.first] < tin[second.first.first];
  return first.first.second < second.first.second;
}
void solve() {
  cin >> n >> m;
  graph.resize(n);
  cost.resize(n);
  pr.resize(n);
  pr_cost.resize(n);
  h.resize(n, -1);
  tin.resize(n);
  tout.resize(n);
  used.resize(n, -1);
  for (int i = 1; i < n; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    graph[i].push_back(a);
    graph[a].push_back(i);
    cost[i].push_back(b);
    cost[a].push_back(b);
  }
  dfs(0, 0);
  for (int i = 0; i < m; i++) {
    int v, a, b;
    cin >> v >> a >> b;
    v--, a--, b--;
    queries.push_back({{v, i}, {a, b}});
  }
  vector<long long> answer(m);
  sort(queries.begin(), queries.end(), cmp);
  dfs_2(queries[0].first.first, 0);
  int cur_v = queries[0].first.first;
  int target_v = -1;
  vector<long long> new_used(n, magic_const);
  for (auto& leaf : leafs) {
    new_used[leaf] = used[leaf];
  }
  segment_tree st(new_used);
  auto up_cur = [&]() {
    st.add_on_segment(0, new_used.size() - 1, -pr_cost[cur_v]);
    st.add_on_segment(tin[cur_v], tout[cur_v] - 1, 2 * pr_cost[cur_v]);
    cur_v = pr[cur_v];
  };
  auto up_target = [&]() {
    st.add_on_segment(0, new_used.size() - 1, pr_cost[target_v]);
    st.add_on_segment(tin[target_v], tout[target_v] - 1,
                      -2 * pr_cost[target_v]);
    target_v = pr[target_v];
  };
  for (int i = 0; i < queries.size(); i++) {
    int l = queries[i].second.first;
    int r = queries[i].second.second;
    target_v = queries[i].first.first;
    int cur_i = queries[i].first.second;
    while (h[cur_v] > h[target_v]) up_cur();
    while (h[target_v] > h[cur_v]) up_target();
    while (cur_v != target_v) {
      up_cur();
      up_target();
    }
    answer[cur_i] = st.get_answer(l, r);
    cur_v = queries[i].first.first;
  }
  for (auto& i : answer) cout << i << "\n";
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  srand(555);
  solve();
}
