#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define elif else if
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define pii pair<int,int>
#define repname(a, b, c, d, e, ...) e
#define rep(...) repname(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define rep0(x) for (int rep_counter = 0; rep_counter < (x); ++rep_counter)
#define rep1(i, x) for (int i = 0; i < (x); ++i)
#define rep2(i, l, r) for (int i = (l); i < (r); ++i)
#define rep3(i, l, r, c) for (int i = (l); i < (r); i += (c))
struct ScalarInput {
template<class T>
operator T(){
T ret;
cin >> ret;
return ret;
}
};
struct VectorInput {
size_t n;
VectorInput(size_t n): n(n) {}
template<class T>
operator vector<T>(){
vector<T> ret(n);
for(T &x : ret) cin >> x;
return ret;
}
};
ScalarInput input(){ return ScalarInput(); }
VectorInput input(size_t n){ return VectorInput(n); }
template<typename T>
void print(vector<T> a){
for(int i=0;i<a.size();i++){
cout<<a[i]<<" \n"[i+1==a.size()];
}
}
template<class T>
void print(T x){
cout << x << '\n';
}
template <class Head, class... Tail>
void print(Head&& head, Tail&&... tail){
cout << head << ' ';
print(forward<Tail>(tail)...);
}
class LCA {
public:
LCA() = default;
LCA(const std::vector<std::vector<int>>& G, int root) : G(G), LOG(32 - __builtin_clz(G.size())), depth(G.size()) {
int V = G.size();
table.assign(LOG, std::vector<int>(V, -1));
dfs(root, -1, 0);
for (int k = 0; k < LOG - 1; ++k) {
for (int v = 0; v < V; ++v) {
if (table[k][v] >= 0) {
table[k + 1][v] = table[k][table[k][v]];
}
}
}
}
int query(int u, int v) const {
if (depth[u] > depth[v]) std::swap(u, v);
// go up to the same depth
for (int k = 0; k < LOG; ++k) {
if ((depth[v] - depth[u]) >> k & 1) {
v = table[k][v];
}
}
if (u == v) return u;
for (int k = LOG - 1; k >= 0; --k) {
if (table[k][u] != table[k][v]) {
u = table[k][u];
v = table[k][v];
}
}
return table[0][u];
}
int dist(int u, int v) const {
return depth[u] + depth[v] - 2 * depth[query(u, v)];
}
int parent(int v, int k) const {
for (int i = LOG - 1; i >= 0; --i) {
if (k >= (1 << i)) {
v = table[i][v];
k -= 1 << i;
}
}
return v;
}
int jump(int u, int v, int k) const {
int l = query(u, v);
int du = depth[u] - depth[l];
int dv = depth[v] - depth[l];
if (du + dv < k) return -1;
if (k < du) return parent(u, k);
return parent(v, du + dv - k);
}
protected:
const std::vector<std::vector<int>>& G;
const int LOG;
std::vector<std::vector<int>> table;
std::vector<int> depth;
void dfs(int v, int p, int d) {
table[0][v] = p;
depth[v] = d;
for (int c : G[v]) {
if (c != p) dfs(c, v, d + 1);
}
}
};
using S=pair<ll,int>;
S op(S a,S b){
return min(a,b);
}
ll inf=(ll)1<<60;
S e(){
return {inf,0};
}
S mapping(ll f,S x){
return {x.first+f,x.second};
}
ll composition(ll f,ll g){
return f+g;
}
ll id(){
return (ll)0;
}
#include <atcoder/lazysegtree>
using namespace atcoder;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,q;
cin>>n>>q;
vll a=input(n);
vector<vector<pair<int,ll>>>child(n);
vector<pair<int,ll>>par(n,{-1,-1});
vector<vector<int>>edge(n);
rep(i,1,n){
int p=input();
ll w=input();
p--;
par[i]={p,w};
child[p].push_back({i,w});
edge[i].push_back(p);
edge[p].push_back(i);
}
vll depth(n,(ll)0);
vi todo;
todo.push_back(~0);
todo.push_back(0);
vi visited;
vi eular_order(n,0);
vi eular_out(n,0);
vector<S> seg_init(n,e());
int tmp=0;
while(!todo.empty()){
int v=todo.back();
todo.pop_back();
if(v>=0){
visited.push_back(v);
eular_order[v]=tmp;
seg_init[tmp]={a[v]-depth[v],v};
tmp+=1;
for(auto [u,w]:child[v]){
depth[u]=depth[v]+w;
todo.push_back(~u);
todo.push_back(u);
}
}
else{
v=~v;
eular_out[v]=tmp;
}
}
lazy_segtree<S,op,e,ll,mapping,composition,id>seg(seg_init);
int M=500;
int bucket_len=(q/M)+1;
vector<vector<pii>>bucket(bucket_len);
vector<pair<pair<int,int>,ll>>queries;
rep(i,q){
int x=input();
int y=input();
ll w=input();
x--;
y--;
bucket[i/M].push_back({i,eular_order[x]});
queries.push_back({{x,y},w});
}
rep(i,bucket_len){
if(i&1){
sort(bucket[i].begin(), bucket[i].end(), [](pair<int, int> A, pair<int, int> B){ return A.second < B.second; });
}
else{
sort(bucket[i].begin(), bucket[i].end(), [](pair<int, int> A, pair<int, int> B){ return A.second > B.second; });
}
}
int query_idx=0;
int v_idx=0;
vector<pair<int,ll>>ans(q);
LCA lca(edge,0);
rep(bucket_i,bucket_len){
for(auto [i,j]:bucket[bucket_i]){
int xi=queries[i].first.first;
int yi=queries[i].first.second;
int frm=visited[v_idx];
int to=visited[j];
if(frm!=to){
int L=lca.query(frm,to);
vi path;
int now=frm;
while(true){
path.push_back(now);
if(now==L)break;
now=par[now].first;
}
vi path2;
now=to;
while(true){
path2.push_back(now);
if(now==L)break;
now=par[now].first;
}
for(int i=path2.size()-2;i>=0;i--){
path.push_back(path2[i]);
}
int m=path.size();
rep(i,m-1){
int now=path[i];
int nxt=path[i+1];
if(par[now].first==nxt){
ll w=par[now].second;
seg.apply(0,n,w);
seg.apply(eular_order[now],eular_out[now],-2*w);
}
else{
ll w=par[nxt].second;
seg.apply(0,n,-w);
seg.apply(eular_order[nxt],eular_out[nxt],2*w);
}
}
}
v_idx=j;
while(query_idx!=i+1){
if(query_idx<i+1){
int y=queries[query_idx].first.second;
ll w=queries[query_idx].second;
seg.apply(eular_order[y],eular_out[y],w);
query_idx+=1;
}
else{
query_idx-=1;
int y=queries[query_idx].first.second;
ll w=queries[query_idx].second;
seg.apply(eular_order[y],eular_out[y],-w);
}
}
ans[i]=seg.all_prod();
}
}
rep(i,q){
print(ans[i].second+1,-ans[i].first);
}
}