#include<cstdio>
#include<vector>
#include<algorithm>
#include<utility>
#define ll long long
using namespace std;
struct seg{
int Max,Min,front,back;
int tag;
};
int n,q,a[50005],siz[50005],fa[50005],top[50005],wc[50005],dep[50005],dfn[50005],rdfn[50005],vistime;
seg w[200005];
vector<int> g[50005];
vector<pair<int,int> > list[2];
void dfs1(int u,int f){
siz[u]=1;
fa[u]=f;
dep[u]=dep[f]+1;
for(auto v:g[u])if(v!=f){
dfs1(v,u);
siz[u]+=siz[v];
if(siz[wc[u]]<siz[v]) wc[u]=v;
}
}
void dfs2(int u,int Top){
dfn[u]=++vistime;
rdfn[vistime]=u;
top[u]=Top;
if(wc[u]!=0){
dfs2(wc[u],Top);
for(auto v:g[u])if(v!=fa[u]&&v!=wc[u]){
dfs2(v,v);
}
}
}
void pushup(seg &z,seg x,seg y){
z.Max=max(x.Max,y.Max);
z.Min=min(x.Min,y.Min);
z.front=max({x.front,y.front,y.Max-x.Min});
z.back=max({x.back,y.back,x.Max-y.Min});
}
seg pushup(seg x,seg y){
seg z;
z.Max=max(x.Max,y.Max);
z.Min=min(x.Min,y.Min);
z.front=max({x.front,y.front,y.Max-x.Min});
z.back=max({x.back,y.back,x.Max-y.Min});
return z;
}
void maketag(int u,int x){
w[u].Max+=x;
w[u].Min+=x;
w[u].tag+=x;
}
void pushdown(int u){
maketag(u*2,w[u].tag);
maketag(u*2+1,w[u].tag);
w[u].tag=0;
}
bool inrange(int l,int r,int L,int R){
return L<=l&&r<=R;
}
bool outofrange(int l,int r,int L,int R){
return r<L||l>R;
}
void update(int u,int l,int r,int L,int R,int x){
if(inrange(l,r,L,R)) maketag(u,x);
else if(!outofrange(l,r,L,R)){
int mid=(l+r)/2;
pushdown(u);
update(u*2,l,mid,L,R,x);
update(u*2+1,mid+1,r,L,R,x);
pushup(w[u],w[u*2],w[u*2+1]);
}
}
seg query(int u,int l,int r,int L,int R){
if(inrange(l,r,L,R)) return w[u];
else{
int mid=(l+r)/2;
pushdown(u);
if(R<=mid) return query(u*2,l,mid,L,R);
if(L>mid) return query(u*2+1,mid+1,r,L,R);
return pushup(query(u*2,l,mid,L,R),query(u*2+1,mid+1,r,L,R));
}
}
void build(int u,int l,int r){
if(l==r){
w[u].Max=w[u].Min=a[rdfn[l]];
w[u].front=w[u].back=0;
w[u].tag=0;
return;
}
int mid=(l+r)/2;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
pushup(w[u],w[u*2],w[u*2+1]);
}
int ask(int l,int r){
list[0].clear();
list[1].clear();
int x=0;
while(top[l]!=top[r]){
if(dep[top[l]]<dep[top[r]]){
swap(l,r);
x^=1;
}
list[x].push_back({dfn[top[l]],dfn[l]});
l=fa[top[l]];
}
if(dep[l]>dep[r]) swap(l,r);
else x^=1;
list[x].push_back({dfn[l],dfn[r]});
reverse(list[1].begin(),list[1].end());
int premax=0,ans=0;
for(int i=0;i<=1;i++){
for(auto j:list[i]){
int u=j.first,v=j.second;
seg Q=query(1,1,n,u,v);
if(i==0) ans=max({ans,premax-Q.Min,Q.back});
else ans=max({ans,premax-Q.Min,Q.front});
premax=max(premax,Q.Max);
}
}
return ans;
}
void Upd(int u,int v,int x){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
update(1,1,n,dfn[top[u]],dfn[u],x);
u=fa[top[u]];
}
update(1,1,n,min(dfn[u],dfn[v]),max(dfn[u],dfn[v]),x);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
scanf("%d",&q);
while(q--){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
printf("%d\n",ask(u,v));
Upd(u,v,w);
}
return 0;
}