hdu3507 斜率优化dp入门

刚开始接触斜率优化dp,做的一道简单的入门题目,这里有一篇论文,前半部分讲的就是这个浅谈数形结合思想在信息学竞赛中的应用
分析:
我们假设 k<j<i 。如果在j的时候决策要比在k的时候决策好,那么也就是
dp[j]+M+(sum[i]sum[j])2<dp[k]+M+(sum[i]sum[k])2
(因为是最小花费嘛,所以优就是小于)两边移项一下,得到:
(dp[j]+sum[j]2(dp[k]+sum[k]2))/(2(sum[j]sum[k]))<sum[i]
我们把 dp[j]sum[j]2 看做是 yj ,把 2sum[j] 看成是 xj
得到 (yjyk)/(xjxk)<sum[i] 左边为斜率的表示
定义 F(j,k)=(yjyk)/(xjxk)

关键的来了:现在从左到右,还是设 k<j<i ,如果 F[i,j]<F[j,k] ,那么j点便永远不可能成为最优解,可以直接将它踢出我们的最优解集。为什么呢?

我们假设 F[i,j]<sum[i] ,那么就是说i点要比j点优,排除j点。
如果 F[i,j]>=sum[i] ,那么j点此时是比i点要更优,但是同时#F[j,k]>F[i,j]>sum[i]#。这说明还有k点会比j点更优,同样排除j点。

然后你会发现其实我们排除的其实就是在二维坐标系当中上凸的点 也就是说我们维护一个下凸的折线就可以得到答案,
代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
#define clr(x) memset(x,0,sizeof(x))
using namespace std;
#define LL long long
LL dat[500005];
LL dp[500005];
LL sum[500005];
LL GetUp(int i,int j)
{
    return dp[i]+sum[i]*sum[i]-dp[j]-sum[j]*sum[j];
}
LL GetDown(int i,int j)
{
    return 2*sum[i]-2*sum[j];
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        clr(dp);
        clr(sum);
        int dque[500005];
        int head,tail;
        head = tail = 0;
        dat[0] = 0;
        dque[tail++] = 0;
        for(int i = 1;i<=n;i++)
        {
            scanf("%lld",&dat[i]);
            sum[i] = dat[i]+sum[i-1];
            while(head+1!=tail && (sum[i]*GetDown(dque[head+1],dque[head])>=GetUp(dque[head+1],dque[head])))
                head++;
            dp[i] = dp[dque[head]] + (sum[i]-sum[dque[head]])*(sum[i]-sum[dque[head]])+m;
            while(tail-1!=head && (GetUp(i,dque[tail-1])*GetDown(dque[tail-1],dque[tail-2])<=GetUp(dque[tail-1],dque[tail-2])*GetDown(i,dque[tail-1])))
                tail--;
            dque[tail++] = i;
        }
        printf("%lld\n",dp[n]);

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值