2018.11.02【HNOI2008】【BZOJ1010】【洛谷P3195】玩具裝箱(斜率優化DP)
阿新 • • 發佈:2018-12-19
洛谷傳送門
解析:
看到平方項多半就是兩種套路,決策單調性和斜率優化,這道題斜率優化可以。
首先還是推DP式子,這個很好想(表示字首和)。
是在是太長了,代換一下,令,則狀態轉移方程化簡為
然後每個決策點設定為,可以斜率優化了。
發現決策的斜率是單調的,單調佇列維護一下凸包就行了。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
cs int N=50004;
int q[N];
int head=1,tail=1;
ll n,L;
ll sum[N],f[N];
inline ll A(int i){return sum[i] +i;}
inline ll B(int i){return sum[i]+i+L+1;}
inline ll calc(int i,int j){
return f[j]+(A(i)-B(j))*(A(i)-B(j));
}
inline ll X(int i){return B(i);}
inline ll Y(int i){return f[i]+B(i)*B(i);}
inline double slope(int i,int j){
return (1.0*Y(i)-Y(j))/(1.0*X(i)-X(j));
}
signed main(){
scanf("%lld%lld",&n,&L);
for(int re i=1;i<=n;++i)scanf("%lld",&sum[i]),sum[i]+=sum[i-1];
for(int re i=1;i<=n;++i){
while(head<tail&&calc(i,q[head])>calc(i,q[head+1]))++head;
f[i]=calc(i,q[head]);
while(head<tail&&slope(i,q[tail-1])<slope(q[tail],q[tail-1]))--tail;
q[++tail]=i;
}
printf("%lld",f[n]);
return 0;
}