The merchant POJ - 3728 lca+ dp思想

参考别人的用在线的lca不知道为什么错。。
https://vjudge.net/solution/2554998



#include<algorithm>
#include<vector>
 #include<cstring>
#include<string>
#include<iomanip>
#include<cstdio>
#include<stack>
#include<iostream>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
#define sf scanf
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a));
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define mod 9901
#define N 100020
#define ULL unsigned long long
#define LL long long
#define inf 0x3f3f3f3f
#define mxn 25020
#define mxe 1002000
#define make_pair

//2017年08月16日08:14:03
int n,q;
int up[22][N],down[22][N],mx[22][N],mi[22][N],w[N],dep[N],fst[N],vv[N<<1],nxt[N<<1];
int tot,fa[22][N];
void init(){ mem(fst,-1);tot=0; }
void add(int u,int v){
    vv[tot]=v;nxt[tot]=fst[u];fst[u]=tot++;
}
void dfs(int u,int p){
    fa[0][u]=p;
    if(p!=-1){
        mx[0][u]=max(w[u],w[p]);
        mi[0][u]=min(w[u],w[p]);
        up[0][u]=max(0,w[u]-w[p]);
        down[0][u]=max(0,w[p]-w[u]);
    }
    else{
        up[0][u]=down[0][u]=-1;
        mx[0][u]=-1;
        mi[0][u]=inf;
    }
    for(int i=fst[u];~i;i=nxt[i]){
        int v=vv[i];
        if(v!=p){
            dep[v]=dep[u]+1;
            dfs(v,u);
        }
    }
}
void init_lca(){
    dep[1]=1;
    dfs(1,-1);
    for(int k=0;k<=20;++k){
        for(int i=1;i<=n;++i){
            if(fa[k][i]==-1)fa[k+1][i]=-1;
            else{
                fa[k+1][i]=fa[k][fa[k][i]];
                if(fa[k+1][i]!=-1){
                    mx[k+1][i]=max(mx[k][i],mx[k][fa[k][i]]);
                    mi[k+1][i]=min(mi[k][i],mi[k][fa[k][i]]);
                    //up[k+1][i]=max(max(up[k][i],up[k][fa[k][i]]),mx[k][fa[k][i]]-mi[k][i]);
                    //down[k+1][i]=max(max(down[k][i],down[k][fa[k][i]]),mx[k][i]-mi[k][fa[k][i]]);
                }
            }
        }
    }
}

int lca(int u,int v){
    if(dep[u]>dep[v]){swap(u,v);}
    for(int k=0;k<20;++k){
        if((dep[v]-dep[u])>>k&1)
            v=fa[k][v];
    }
    if(u==v)return u;
    for(int k=19;k>=0;--k){
        if(fa[k][u]!=fa[k][v])
            u=fa[k][u],v=fa[k][v];
    }
    return fa[0][u];
}

int qmax1(int u,int p){
     int ret=0,M=0;
     if(u==p)return 0;
     for(int k=19;k>=0;--k){
         if(fa[k][u]!=-1&&dep[fa[k][u]]>=dep[p]){
            ret=max(ret,up[k][u]);
             ret=max(ret,M-mi[k][u]);
             M=max(M,mx[k][u]);
             u=fa[k][u];
         }
     }
     pf("res: %d\n",ret);
     return ret;
}
int qmax2(int u,int p){
    if(u==p)return 0;
    pf("%d %d\n",u,p);
    int ret=0,M=inf;
    for(int k=19;k>=0;--k){
        if(fa[k][u]!=-1&&dep[fa[k][u]]>=dep[p]){
            pf("k: %d\n",k);
            pf("k:%d  u:%d    down[k][u]: %d\n",k,u,down[k][u]);
            ret=max(ret,down[k][u]);
            ret=max(ret,mx[k][u]-M);
            M=min(M,mi[k][u]);
            u=fa[k][u];
        }
    }
     pf("res: %d\n",ret);
    return ret;
}
int cas=0;
int  solve(int u,int v){
    int p=lca(u,v);
    pf("CAs %d :%d\n",++cas,p);
    if(p==u){return qmax2(v,u);}
    else if(p==v){return qmax1(u,v);}
    int ans=0;
    ans=max(ans,qmax1(u,p));
    ans=max(ans,qmax2(v,p));
    pf("ans: %d\n",ans);
    int MX=0,MI=inf;
    for(int k=19;k>=0;--k){
        if(fa[k][u]!=-1&&dep[fa[k][u]]>=dep[p]){
            MX=max(MX,mx[k][u]);
            u=fa[k][u];
        }
        if(fa[k][v]!=-1&&dep[fa[k][v]]>=dep[p]){
            MI=min(MI,mi[k][v]);
            v=fa[k][v];
        }
    }
    ans=max(ans,MX-MI);
    return ans;
}
int main(){
    freopen("in.txt","r",stdin);
    while(~sf("%d",&n)){
        init();
        rep(i,1,n){sf("%d",&w[i]);}
        rep(i,1,n-1){int u,v;sf("%d%d",&u,&v);add(u,v),add(v,u);}
        init_lca();
        sf("%d",&q);
        while(q--){
            int u,v;sf("%d%d",&u,&v);
            pf("%d\n",solve(u,v));
        }
        pf("test\n");
        for(int i=1;i<=n;++i){
            for(int k=0;k<=2;++k){
                pf("%d ",down[k][i]);
            }puts("");
        }
    }
}

这个地方还看到别人用并查集写,挺好的。。
参考http://blog.csdn.net/sdj222555/article/details/43003179

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值