http://acm.hust.edu.cn/vjudge/contest/view.action?cid=34528#problem/L
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 50010;
const int POW = 17;
const int INF = 0x3f3f3f3f;
int val[MAXN], head[MAXN], cnt;
int parent[MAXN][POW], dep[MAXN], mmin[MAXN][POW], mmax[MAXN][POW], up[MAXN][POW], down[MAXN][POW];
/*
*parent[i][j]: 表示距离顶点i为2^j的祖先顶点的编号
*up[i][j]: i->距离i为2^j的祖先顶点最大收益
*down[i][j]: 距离i为2^j的祖先顶点->i顶点的最小收益
*mmin[i][j]: i->距离i为2^j的祖先顶点的最小顶点的权值
*mmax[i][j]: i->距离i为2^j的祖先顶点的最大顶点的权值
*因此对于一组询问(u,v) ans = max(getmax_up(u, lca(u,v)), getmax_dwon(v, lca(u,v)), getmax(v, lca(u,v))-getmin(u, lca(u,v)))
*/
struct Edge
{
int v, next;
Edge() {}
Edge(int t_v, int t_next) : v(t_v), next(t_next) {}
}edge[2*MAXN];
void addedge(int u, int v)
{
edge[cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt++;
edge[cnt].v = u;
edge[cnt].next = head[v];
head[v] = cnt++;
}
void Init(int n)
{
cnt = 0;
memset(head, -1, sizeof(head));
memset(dep, 0, sizeof(dep));
memset(parent, 0, sizeof(parent));
for(int i = 1; i <= n; ++i)
{
for(int j = 0; j < POW; ++j)
{
mmin[i][j] = mmax[i][j] = up[i][j] = down[i][j] = 0;
}
}
}
void dfs(int u, int fa)
{
int i, j;
dep[u] = dep[fa] + 1;
for(i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
if(v == fa) continue;
////////////////////////////////////////////////////////////////////////////////
parent[v][0] = u;
mmin[v][0] = min(val[u], val[v]);
mmax[v][0] = max(val[u], val[v]);
up[v][0] = val[u] - val[v];
down[v][0] = val[v] - val[u];
for(j = 1; (1<<j) <= dep[u] + 1; j++)
{
parent[v][j] = parent[parent[v][j-1]][j-1];
mmin[v][j] = min(mmin[v][j-1], mmin[parent[v][j-1]][j-1]);
mmax[v][j] = max(mmax[v][j-1], mmax[parent[v][j-1]][j-1]);
up[v][j] = max(up[v][j-1], up[parent[v][j-1]][j-1]);
up[v][j] = max(up[v][j], mmax[parent[v][j-1]][j-1] - mmin[v][j-1]);
down[v][j] = max(down[v][j-1], down[parent[v][j-1]][j-1]);
down[v][j] = max(down[v][j], mmax[v][j-1] - mmin[parent[v][j-1]][j-1]);
}
/////////////////////////////////////////////////////////////////////////////////
dfs(v, u);
}
return ;
}
int LCA(int u, int v)
{
int i;
if(dep[u] > dep[v]) u ^= v, v ^= u, u ^= v;
if(dep[u] < dep[v])
{
int del = dep[v] - dep[u];
for(i = 0; i < POW; i++)
if(del & (1<<i))
v = parent[v][i];
}
if(u != v)
{
for(i = POW - 1; i >= 0; i--)
if(parent[u][i] != parent[v][i])
u = parent[u][i], v = parent[v][i];
u = parent[u][0], v = parent[v][0];
}
return u;
}
int getmax_up(int u, int v)
{
int ans = 0, i, tmp = INF;
int del = dep[u] - dep[v];
for(i = POW-1; i >= 0; i--)
{
if(del & (1<<i))
{
ans = max(ans, up[u][i]);
ans = max(ans, mmax[u][i] - tmp);
tmp = min(tmp, mmin[u][i]);
u = parent[u][i];
}
}
return ans;
}
int getmax_down(int u, int v)
{
int ans = 0, i, tmp = 0;
int del = dep[u] - dep[v];
for(i = POW-1; i >= 0; i--)
{
if(del & (1<<i))
{
ans = max(ans, down[u][i]);
ans = max(ans, tmp - mmin[u][i]);
tmp = max(tmp, mmax[u][i]);
u = parent[u][i];
}
}
return ans;
}
int getmax(int u, int v)
{
int ans = 0, i;
int del = dep[u] - dep[v];
for(i = POW-1; i >= 0; i--)
{
if(del & (1<<i))
{
ans = max(ans, mmax[u][i]);
u = parent[u][i];
}
}
return ans;
}
int getmin(int u, int v)
{
int ans = INF, i;
int del = dep[u] - dep[v];
for(i = POW-1; i >= 0; i--)
{
if(del & (1<<i))
{
ans = min(ans, mmin[u][i]);
u = parent[u][i];
}
}
return ans;
}
void solve(int u, int v)
{
int lca = LCA(u, v);
int a, b, c, d;
a = getmax_up(u, lca);
b = getmax_down(v, lca);
c = getmin(u, lca);
d = getmax(v, lca);
printf("%d\n", max(max(a, b), d - c));
}
int main()
{
//freopen("aa.in", "r", stdin);
int i, u, v, n, q;
scanf("%d", &n);
Init(n);
for(i = 1; i <= n; i++)
scanf("%d", &val[i]);
for(i = 1; i < n; i++)
{
scanf("%d %d", &u, &v);
addedge(u, v);
}
dfs(1, 0);
scanf("%d", &q);
for(i = 1; i <= q; i++)
{
scanf("%d %d", &u, &v);
solve(u, v);
}
return 0;
}