• bzoj3427小P的牧场(斜率优化dp)


    小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被控制)(如果它西边不存在控制站,那么它控制西边所有的牧场),每个牧场被控制都需要一定的花费(毕竟在控制站到牧场间修建道路是需要资源的嘛~),而且该花费等于它到控制它的控制站之间的牧场数目(不包括自身,但包括控制站所在牧场)乘上该牧场的放养量,在第i个牧场建立控制站的花费是ai,每个牧场i的放养量是bi,理所当然,小P需要总花费最小,但是小P的智商有点不够用了,所以这个最小总花费就由你来算出啦。

    Solution

    感觉自己学的有点死。

    直接dp感觉比较困难,考虑正难则反,因为第n个点肯定是要放的,那么在之前放会使代价减小,所以我们先算出只在n个点放的代价,在倒着dp一下算减小的贡献。

    方程,dp[i]=max{dp[j]+sum[i]*(j-i)-a[i]}.

    整理可得sum[i]*j-(sum[i]*i+a[i]+dp[i])=-dp[j].

    因为我们要求dp[i]最大值,所以我们要维护截距最小值,也就是一个下凸包。

    emm,感觉自己维护了一个下凸包,连样例都过不了,纠结了一晚上。。。

    因为我们的dp过程是倒着做的,所以我们的维护是反着的23333。

    Code

    #include<iostream>
    #include<cstdio>
    #define X(i) i
    #define Y(i) -dp[i]
    #define N 1000002
    using namespace std;
    typedef long long ll;
    ll tot,sum[N],ans,dp[N];
    int a[N],q[N],h,t,n,b[N];
    inline double calc(int x,int y){
        return (double)((double)Y(y)-Y(x))/((double)X(y)-X(x));
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        for(int i=1;i<=n;++i)scanf("%d",&b[i]),sum[i]=b[i]+sum[i-1];
        for(int i=1;i<n;++i)tot+=1ll*(n-i)*b[i];
        tot+=a[n];
        q[h=t=1]=n;ans=0;
        for(int i=n-1;i>=1;--i){
            while(h<t&&calc(q[h],q[h+1])>sum[i])h++;
            dp[i]=dp[q[h]]+(q[h]-i)*sum[i]-a[i];
            while(h<t&&calc(q[t-1],q[t])<calc(q[t],i))t--;
            q[++t]=i; 
            ans=max(ans,dp[i]);
        }
        cout<<tot-ans;
        return 0;
    } 
  • 相关阅读:
    db2构建临时结果集
    db2 in out inout
    杂文Python
    db2记录去重
    oop设计模式抽象总结
    Linux 查看发行版版本信息和内核版本
    第二节课:功能测试需求分析方法
    mybatis or的用法
    java中&& 的运算优先级高于||
    下载根目录下的pdf文件, 浏览器下载
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9846408.html
Copyright © 2020-2023  润新知