题目描述
Z 国是一个拥有N 个岛的国家。这N 个岛用N-1 条桥来连接,且任意两个岛之间都可以互达。
某商人听说Z 国是一个很富有的国家,所以他想到Z 国闯一闯。经过他仔细的观察,他发现某样商品特别受欢迎,而且由于各岛之间沟通联系不够多,所以这样物品在每个岛的价格可能都不同。
Task:商人开始在编号为x 的岛上,然后他要走到编号为y 的岛上。在这期间,他可以在x 岛y 的路径上买一件商品,和卖一件商品。,注意,仅能买一件和卖一件!显然你要计算商人从岛x 到岛y 最多能赚多少钱。
Input
输入第一行有一个整数N(1≤n≤50000),表示Z 国有N 个岛。
接下来有N 行,每行一个整数Ci(1≤Ci≤50000),第N+i 行的Ci 表示商品在岛i 的价
格。
再接下来有N-1 行,每行两个整数x,y(1≤x,y≤50000),表示岛x 和岛y 之间有一条
桥。
接下来有一个整数M,表示有M 个询问。
然后M 行,每行两个整数,x,y(1≤x,y≤50000),表示询问你,商人从岛x 到岛y 最多
能赚多少钱?
Output
对于每次询问,如果商人能赚到钱,则输出最多能赚多少钱。
如果不能赚钱,就输出0(你可以这样理解——亏本生意谁都不会做^_^)
Sample Input
4
1
2
3
4
1 2
1 4
2 3
3
1 3
3 1
1 4
Sample Output
2
0
3
Data Constraint
Hint
数据约定:
对于30%的数据, 1≤N,M≤100
对于60%的数据,1≤N,M≤1000
对于100%的数据,1≤N,M≤50000
分析
这题很容易想到LCA作为x,y的中间点
然后如何求最多赚的钱呢?
其实只要x和y分别从自己一个一个点地跑到LCA,途中发现最大值更新,如果最小值更新,最大值清零,同时用ans记录所有情况的最优值即可
(我就是没有用ans记录所有情况才拿了10分。。。)
巨尴尬
#include <iostream>
#include <cstdio>
#define rep(i,a,b) for (i=a;i<=b;i++)
using namespace std;
int n,m,big,ans;
int mx,mi,f;
int d[50001];
int p[50001][21];
int list[50001];
struct E
{
int u,v,next;
}a[100001];
int cnt;
int b[50001];
void add(int u,int v)
{
a[++cnt].u=u;a[cnt].v=v;a[cnt].next=list[u];list[u]=cnt;
}
void init()
{
int i,x,y;
scanf("%d",&n);
x=0;
rep(i,1,n)
{
scanf("%d",&b[i]);
if (b[i]>x)
{
big=i;
x=b[i];
}
}
rep(i,1,n-1)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
}
void dfs(int x)
{
int i;
for (i=list[x];i;i=a[i].next)
if (!d[a[i].v])
{
d[a[i].v]=d[x]+1;
p[a[i].v][0]=x;
dfs(a[i].v);
}
}
void power()
{
int i,j;
rep(j,1,20)
rep(i,1,n)
p[i][j]=p[p[i][j-1]][j-1];
}
void doit()
{
d[big]=1;
dfs(big);
power();
}
int lca(int x,int y)
{
int a=x,b=y,i;
if (d[a]<d[b]) swap(a,b);
for (i=20;i>=0;i--)
if (d[p[a][i]]>=d[b])
a=p[a][i];
if (a==b) return a;
for (i=20;i>=0;i--)
if (p[a][i]!=p[b][i])
{
a=p[a][i];
b=p[b][i];
}
return p[a][0];
}
void dfs1(int x)
{
if (b[x]<mi)
{
mi=b[x];
mx=0;
}
mx=max(mx,b[x]);
ans=max(ans,mx-mi);
if (x==f) return;
dfs1(p[x][0]);
}
void dfs2(int x)
{
if (x==f) return;
dfs2(p[x][0]);
if (b[x]<mi)
{
mi=b[x];
mx=0;
}
mx=max(mx,b[x]);
ans=max(ans,mx-mi);
}
void print()
{
int i,a,b;
scanf("%d",&m);
rep(i,1,m)
{
scanf("%d%d",&a,&b);
ans=0;
f=lca(a,b);
mi=2147483647;
dfs1(a);
dfs2(b);
printf("%d\n",ans);
}
}
int main()
{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
init();
doit();
print();
}