题意:有一种商品。在N个城市中的价格都不一样、给定N个点和N-1条边。有Q个询问。每个询问的内容为:
商人从u–>v这条路径上所能获得的最大利润是多少、商人只可以在某一个点买进东西。在这个点之后卖出它、

思路:
由于给定的是一颗简单树。很容易就想到可以用LCA来做。难点在于。怎么求出u–>t–>v的最大利润,
t==lca(u,v)
可以想到并查集的更新操作。
对于每一个询问的u和v 如果我知道以下内容:

  1. u到最近的祖先的最大利润up[u]  和 最近祖先到u的最大利润 down[u]
  2. u到最近祖先的最大值maxx[u]  和最小值 minx[u]
    那么我们就可以很容易求出u–>v的最大利润了
    u–>v的最大利润 = max(up[u],down[v],maxx[v]-minx[u])
    但是主要的问题怎么解决
    通过tarjan递归的时候结局 和 并查集中的Find来处理。
    详情代码:
//author: CHC
//First Edit Time: 2014-08-02 21:59
//Last Edit Time: 2014-08-02 22:40
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
#define MAXN 50010
struct Q
{
int u,v,id,dir;
Q(){}
Q(int _u,int _v,int _id,int _dir):u(_u),v(_v),id(_id),dir(_dir){}
};
int path[MAXN];
vector <int> e[MAXN];
vector <Q> h[MAXN],q[MAXN];
int maxx[MAXN],minx[MAXN],up[MAXN],down[MAXN],n,ans[MAXN];
int vis[MAXN];
inline void init(){
for(int i=0;i<=n+3;i++){
path[i]=i;
vis[i]=up[i]=down[i]=0;
e[i].clear();
h[i].clear();
q[i].clear();
}
}
int Find(int x){
if(x==path[x])return x;
int px=path[x];
path[x]=Find(path[x]);
up[x]=max(maxx[px]-minx[x],max(up[x],up[px]));
down[x]=max(maxx[x]-minx[px],max(down[x],down[px]));
maxx[x]=max(maxx[x],maxx[px]);
minx[x]=min(minx[x],minx[px]);
return path[x];
}
void LCA(int u){
vis[u]=1;
for(int i=0;i<(int)q[u].size();i++){
Q &next=q[u][i];
if(vis[next.v]){
int lca=Find(next.v);
h[lca].push_back(next);
}
}
for(int i=0;i<(int)e[u].size();i++){
int v=e[u][i];
if(!vis[v]){
LCA(v);
path[v]=u;
}
}
for(int i=0;i<(int)h[u].size();i++){
Q now=h[u][i];
Find(now.u); Find(now.v);
if(!now.dir) swap(now.u,now.v);
ans[now.id]=max(up[now.u],down[now.v]);
ans[now.id]=max(ans[now.id],maxx[now.v]-minx[now.u]);
}
}
int main()
{
while(~scanf("%d",&n)){
init();
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
maxx[i]=minx[i]=x;
}
for(int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
int qq;
scanf("%d",&qq);
for(int i=0,x,y;i<qq;i++){
scanf("%d%d",&x,&y);
q[x].push_back(Q(x,y,i,1));
q[y].push_back(Q(y,x,i,0));
}
LCA(1);
for(int i=0;i<qq;i++)
printf("%d\n",ans[i]);
}
return 0;
}