HDU3507 Print Article(斜率优化+单调队列)

大佬的斜率优化博客,写的很好

https://www.cnblogs.com/orzzz/p/7885971.html

DP的斜率优化同四边形优化和数据结构优化类似,都是用一种方法快速找到最优的状态转移,以到达优化的目的。一次O(n)转移可以变成log或者常数级别的。

这个题斜率优化的步骤就是,比较不同的状态转移,写成斜率的形式,发现他们存在一个关系,只需要维护一个下凸的凸包结构,最优状态转移的点一定在这个凸包上,剔除了很多不可能是最优的状态转移点。这个题还存在一个单调性,维护单调队列即可,因为每次找到最优点前面的点都可在凸包上剔除。

这个题算斜率优化的模板,思路推导就见上面的博客吧,我也不会搞LaTeX。

1A代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e5+10;
ll dp[N];
ll a[N];
ll pre[N];
ll que[N];
int n,m;
ll get_up(int i,int j){
    return dp[j]+pre[j]*pre[j]-dp[i]-pre[i]*pre[i];
}
ll get_down(int i,int j){
    return pre[j]-pre[i];
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        pre[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            pre[i]=pre[i-1]+a[i];
        }
        int head=0,tail=0;
        que[tail]=0;
        for(int i=1;i<=n;i++){
            while(head<tail&&get_up(que[head],que[head+1])<=2*pre[i]*get_down(que[head],que[head+1]))
                head++;
                //找到一个最优的转移,时间复杂度为为常数,保证队列非空
            dp[i]=dp[que[head]]+(pre[i]-pre[que[head]])*(pre[i]-pre[que[head]])+m;
            while(head<tail&&get_up(que[tail],i)*get_down(que[tail-1],que[tail])<=get_up(que[tail-1],que[tail])*get_down(que[tail],i))
                tail--;
            que[++tail]=i;

        }
        cout<<dp[n]<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值