hdu3507 斜率優化dp入門
阿新 • • 發佈:2019-02-09
剛開始接觸斜率優化dp,做的一道簡單的入門題目,這裡有一篇論文,前半部分講的就是這個淺談數形結合思想在資訊學競賽中的應用
分析:
我們假設
(因為是最小花費嘛,所以優就是小於)兩邊移項一下,得到:
我們把
得到 j−yk)/(xj−xk)<sum[i]
定義
關鍵的來了:現在從左到右,還是設
我們假設
如果
然後你會發現其實我們排除的其實就是在二維座標系當中上凸的點 也就是說我們維護一個下凸的折線就可以得到答案,
程式碼:
#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;
}