/*
    题意:给出一棵节点有值的树,给出Q个询问(a,b),问从a到b的最大盈利(即:先在最小值买入,再在最大值卖出)
    我有想过用一个新序列w2-w1 , w3-w2 ,  , wn-wn-1
    这样只需用O(n)求得最大子段和即为结果Max-Min了
    但Q很大,每次都找一个路径会超时
    用类似Tarjan算法进行处理,但在find()那里要修改一下
    对每个几点记录4个值
    up[v] 表示从v到目前的根的最大盈利
    down[v] 从目前的根到v的最大盈利
    Max[v]表示到目前的根的最大值
    Min[v]表示到目前的根的最小值
    转移看update!    
    在LCA(u,v)处再来计算,这样那四个值才是正确的值!!
*/

#include
<cstdio>
#include
<cstring>
#include
<vector>
#include
<algorithm>

using namespace std;

inline 
int min(int a,int b){return a<b?a:b;}
inline 
int max(int a,int b){return a>b?a:b;}

const int MAXN = 50005;

struct Node
{
    
int w,next;
}
nodes[MAXN*4];

struct NodeQ
{
    
int u,v,id,next;
}
nodeqs[MAXN*2];

int Min[MAXN],Max[MAXN],down[MAXN],up[MAXN];
int fa[MAXN],w[MAXN],ans[MAXN];
int G[MAXN],Q[MAXN],D[MAXN];
bool vi[MAXN];
int N,K;
int allocq,alloc;

void addG(int a,int b)
{
    alloc
++;
    nodes[alloc].w
=b,nodes[alloc].next=G[a];
    G[a]
=alloc;
}

void addQ(int a,int b,int id)
{
    allocq
++;
    nodeqs[allocq].u
=a,nodeqs[allocq].v=b,nodeqs[allocq].id=id;
    nodeqs[allocq].next
=Q[a];Q[a]=allocq;
}

void addD(int a,int b)
{
    alloc
++;
    nodes[alloc].w
=b;nodes[alloc].next=D[a];
    D[a]
=alloc;
}

/*
       Min[a]         Max[a]
     a -------> fa[a] --------> root
*/

void update(int x)
{
    
if(x!=fa[x]){
        update(fa[x]);
//先处理好上面的
        up[x]=max(up[x],max(up[fa[x]],Max[fa[x]]-Min[x]));//注意是Min[x],不是w[x],因为有路径压缩
        down[x]=max(down[x],max(down[fa[x]],Max[x]-Min[fa[x]]));//同理是Max[x]
        Max[x]=max(Max[x],Max[fa[x]]);
        Min[x]
=min(Min[x],Min[fa[x]]);
        fa[x]
=fa[fa[x]];
    }

}

void Tarjan(int x)
{
    vi[x]
=1;
    
for(int son=Q[x];son;son=nodeqs[son].next){
        
int v=nodeqs[son].v;
        
if(vi[v]){
            update(v);
            addD(fa[v],son);
//保存u->lca->v的询问,然后在到达lca那里处理,这样那四个值才是正确的
        }

    }

    
for(int son=G[x];son;son=nodes[son].next){
        
int v=nodes[son].w;
        
if(!vi[v]){
            Tarjan(v);
            fa[v]
=x;
        }

    }

    
for(int son=D[x];son;son=nodes[son].next){//lca为x,处理u,v
        int u=nodeqs[nodes[son].w].u,v=nodeqs[nodes[son].w].v,id=nodeqs[nodes[son].w].id;
        update(u);update(v);
//u,v更新,lca会为x,因为fa[x]=x
        if(id<0){id=-id;swap(u,v);}
        ans[id]
=max(up[u],down[v]);
        ans[id]
=max(ans[id],Max[v]-Min[u]);
    }

}

int main()
{
    
while(~scanf("%d",&N)){
        memset(G
+1,0,sizeof(int)*N);
        memset(Q
+1,0,sizeof(int)*N);
        memset(D
+1,0,sizeof(int)*N);
        memset(up
+1,0,sizeof(int)*N);
        memset(down
+1,0,sizeof(int)*N);
        memset(ans
+1,0,sizeof(int)*N);
        memset(vi
+1,0,sizeof(bool)*N);
        alloc
=allocq=0;
        
for(int i=1;i<=N;i++){
            scanf(
"%d",&w[i]);
            Max[i]
=Min[i]=w[i];
            fa[i]
=i;
        }

        
int a,b;
        
for(int i=1;i<N;i++){
            scanf(
"%d%d",&a,&b);
            addG(a,b);
            addG(b,a);
        }

        scanf(
"%d",&K);
        
for(int i=1;i<=K;i++){
            scanf(
"%d%d",&a,&b);
            addQ(a,b,i);
            addQ(b,a,
-i);
        }

        Tarjan(
1);
        
for(int i=1;i<=K;i++)
            printf(
"%d\n",ans[i]);
    }

    
return 0;
}