#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();   }