zoukankan      html  css  js  c++  java
  • POJ3728 The merchant(倍增LCA算法+树形DP)

    题意:

    给出N个点,和每个点物品的售价,现在有一个商人,要从u点到v点,他想在路上多赚点钱。他可以从一个城市买物品,然后再卖到另一个城市,但买卖只允许一次,且不能回头走 问最多能赚多少

    题解:

    对于一个询问, 假设u,v的LCA是f

    有三种可能, 一个是从u到f 买卖了。 一个是从f到v买卖了,  一个是从u到f之间买了,从v到f卖了

    在原有倍增数组的基础上,新开四个数组,分别表示:

    dp_max:向上走2^k步之间的最高价格

    dp_min:向上走2^k步之间的最低价格

    dp_up:从u向上走2^k步的最大利润

    dp_down:向下走2^k步到u的最大利润

    然后对于每次询问,比较三个值:

    从u到f买卖的最大利润

    从f到v买卖的最大利润

    从u到f买,从v到f卖的最大利润

    俺又自闭了,智商跟不上...

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1e5;
    int N;
    int head[maxn];
    int tol;
    struct node {
        int u;
        int v;
        int next;
    }edge[maxn];
    void addedge (int u,int v) {
        edge[tol].u=u;
        edge[tol].v=v;
        edge[tol].next=head[u];
        head[u]=tol++;
    } 
    int weight[maxn];
    int h[maxn];
    int father[20][maxn];
    int dp_max[20][maxn];//向上走2^k步之间的最高价格
    int dp_min[20][maxn];//向上走2^k步之间的最低价格
    int dp_up[20][maxn];//从u向上走2^k的最大利润
    int dp_down[20][maxn];//向下走2^k步到u的最大利润 
    void dfs (int x) {
        for (int i=head[x];i!=-1;i=edge[i].next) {
            int v=edge[i].v;
            if (v==father[0][x]) continue;
            father[0][v]=x;
            h[v]=h[x]+1;
            dp_up[0][v]=max(weight[x]-weight[v],0);
            dp_down[0][v]=max(weight[v]-weight[x],0);
            dp_max[0][v]=max(weight[v],weight[x]);
            dp_min[0][v]=min(weight[v],weight[x]);
            dfs(v);
        }
    }
    int lca (int x,int y) {
        if (h[x]<h[y]) swap(x,y);
        for (int i=17;i>=0;i--) 
            if (h[x]-h[y]>>i) x=father[i][x];
        if (x==y) return x;
        for (int i=17;i>=0;i--) 
            if (father[i][x]!=father[i][y]) {
                x=father[i][x];
                y=father[i][y];
            }
        return father[0][x];
    }
    int up (int u,int k,int &Min) {
        Min=1e9;
        int ans=0,preMin=1e9;
        for (int i=16;i>=0;i--) {
            if (k>>i&1) {
                Min=min(Min,dp_min[i][u]);
                ans=max(ans,dp_up[i][u]);
                ans=max(ans,dp_max[i][u]-preMin);
                preMin=min(preMin,dp_min[i][u]);
                u=father[i][u];
            }
        } 
        return ans;
    }
    int down (int u,int k,int &Max) {
        Max=0;
        int ans=0,preMax=0;
        for (int i=16;i>=0;i--) {
            if (k>>i&1) {
                Max=max(Max,dp_max[i][u]);
                ans=max(ans,dp_down[i][u]);
                ans=max(ans,preMax-dp_min[i][u]);
                preMax=max(preMax,dp_max[i][u]);
                u=father[i][u];
            }
        }
        return ans;
    }
    int main () {
        scanf("%d",&N);
        for (int i=1;i<=N;i++)
            scanf("%d",&weight[i]);
        memset(head,-1,sizeof(head));
        memset(dp_max,0,sizeof(dp_max));
        memset(dp_min,0x3f,sizeof(dp_min));
        tol=0;
        for (int i=0;i<N-1;i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        int q;
        dfs(1);
        for (int i=1;i<=17;i++) 
            for (int j=1;j<=N;j++) {
                father[i][j]=father[i-1][father[i-1][j]];
                int mid=father[i-1][j];
                dp_max[i][j]=max(dp_max[i-1][j],dp_max[i-1][mid]);
                dp_min[i][j]=min(dp_min[i-1][j],dp_min[i-1][mid]);
                dp_up[i][j]=max(max(dp_up[i-1][j],dp_up[i-1][mid]),dp_max[i-1][mid]-dp_min[i-1][j]);
                dp_down[i][j]=max(max(dp_down[i-1][j],dp_down[i-1][mid]),dp_max[i-1][j]-dp_min[i-1][mid]);
            }
        scanf("%d",&q);
        for (int i=1;i<=q;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            int Min=1e9,Max=-1;
            int r=lca(x,y);
            int up_w=up(x,h[x]-h[r],Min);
            int down_w=down(y,h[y]-h[r],Max);
            printf("%d
    ",max(max(up_w,down_w),Max-Min));
        }
    }
  • 相关阅读:
    一千行MySQL学习笔记(七)
    一千行MySQL学习笔记(六)
    一千行MySQL学习笔记(五)
    一千行MySQL学习笔记(四)
    一千行MySQL学习笔记(三)
    活动时的测试点及注意事项
    [AX2012]关于财务默认维度
    [AX]AX2012 R2 HR Jobs, Positions, Department和Workers
    [AX]AX2012 R2 EP员工自助服务中的产品不能显示图片的问题
    [AX]AX2012 R2 采购订单的“Request change”
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12530533.html
Copyright © 2011-2022 走看看