1. 程式人生 > >題解 【POJ3728】The merchant(LCA)

題解 【POJ3728】The merchant(LCA)

分享圖片 gist The open chan stdout node .org 圖片

題意:一棵樹有N個城市,每個城市商品價格不一樣,Q個詢問,問從u出發到達v點,每個城市只能經過一次的最大利潤

max min數組存u城到u的第2^i個祖先路徑上的最值

答案就是u-v路徑上的最大值-最小值

真的是這樣嗎?

仔細想想,買入點可能在賣出點之後嗎?當然不行

於是把路徑分成兩段

技術分享圖片

問題就變成下列三種情況

購買和賣出都在A段中完成

購買和賣出都在B段中完成

在A段中購買,B段中賣出

然後將A,B段分別進行處理(感覺像是dp的思想)

這還不夠,還要分方向進行處理

shun【u】表示從u往LCA走 dao【u】表示從LCA往u走

最後別忘了處理U-LCA購買,LCA-V賣出的情況

#include<cstdio>
#define inf 0x3f3f3f3f
#define N 50005 

int n,q,a,b;
int cnt;
int val[N],head[N],dep[N];
int f[N][21],mx[N][21],mn[N][21],shun[N][21],dao[N][21];

void inline swap(int &a,int &b){
    a^=b^=a^=b;
}

inline int max(int x,int y){
    if(x>y) return x;
    return y;
}

inline int min(int x,int y){
    if(x<y) return x;
    return y;
}

struct node{
    int v,nex;
}e[N*2];

inline void add(int u,int v){
    cnt++;
    e[cnt].v=v;
    e[cnt].nex=head[u];
    head[u]=cnt;
}
 
inline void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    f[u][0]=fa;
    mx[u][0]=max(val[u],val[fa]);
    mn[u][0]=min(val[u],val[fa]);
    shun[u][0]=max(0,val[fa]-val[u]);
    dao[u][0]=max(0,val[u]-val[fa]);
    for(register int i=1;i<=20;++i){
        f[u][i]=f[f[u][i-1]][i-1];
        mx[u][i]=max(mx[u][i-1],mx[f[u][i-1]][i-1]);
        mn[u][i]=min(mn[u][i-1],mn[f[u][i-1]][i-1]);
        int k=mx[f[u][i-1]][i-1]-mn[u][i-1];
        int p=mx[u][i-1]-mn[f[u][i-1]][i-1];
        shun[u][i]=max(k,max(shun[u][i-1],shun[f[u][i-1]][i-1]));
        dao[u][i]=max(p,max(dao[u][i-1],dao[f[u][i-1]][i-1]));
    }
    for(register int i=head[u];i;i=e[i].nex){
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u);
    }
}

inline int lca(int a,int b){
    int ans=0,Max=0,Min=0x3f3f3f3f;
    Max=val[b],Min=val[a];
    if(dep[a]<dep[b]){
        for(register int i=20;i>=0;--i){
            if(dep[a]>dep[f[b][i]]) continue;
            ans=max(ans,max(Max-mn[b][i],dao[b][i]));
            Max=max(Max,mx[b][i]);
            b=f[b][i];
        }
    }
    else{
        for(register int i=20;i>=0;--i){
            if(dep[b]>dep[f[a][i]]) continue;
            ans=max(ans,max(mx[a][i]-Min,shun[a][i]));
            Min=min(Min,mn[a][i]);
            a=f[a][i];
        }
    }
    if(a==b) return ans;
    for(register int i=20;i>=0;--i){
        if(f[b][i]==f[a][i]) continue;
        ans=max(ans,max(mx[a][i]-Min,shun[a][i]));
        ans=max(ans,max(Max-mn[b][i],dao[b][i]));
        Max=max(Max,mx[b][i]);
        Min=min(Min,mn[a][i]);
        a=f[a][i];
        b=f[b][i];
    }
    ans=max(ans,shun[a][0]);
    ans=max(ans,dao[b][0]);
    Max=max(Max,mx[b][0]);
    Min=min(Min,mn[a][0]);
    ans=max(ans,Max-Min);
    return ans;
}

int main(){
//  freopen("1.in","r",stdin);
//  freopen("E.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d",&val[i]);
    }
    for(int i=1;i<n;++i){
        scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
    }
    dfs(1,0);
    scanf("%d",&q);
    for(int i=1;i<=q;++i){
        scanf("%d%d",&a,&b);
        printf("%d\n",lca(a,b));
    }
    getchar();
    return 0;
}

題解 【POJ3728】The merchant(LCA)