[LCA]Road

题目描述

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();
}

猜你喜欢

转载自blog.csdn.net/ssl_qyh0ice/article/details/80029568
lca