HNOI2008 玩具装箱TOY

题目链接

题解

一道很简单的斜率优化DP。
设$f(i)$表示装到第$i$个玩具为止的时候,最小的花费。
那么


就有了

使用斜率优化方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cctype>
#define INF 2000000000
using namespace std;
typedef long long ll;
int n,cnt=0,que[50005]={0},l=1,r=1;
ll f[50005],c[50005]={0},sum[50005]={0},L;
double sqr(double f){
return f*f;
}
double slope(int j,int k){
return (f[k]+sqr(k+sum[k])-f[j]-sqr(j+sum[j]))/(k-j+sum[k]-sum[j]);
}
int read(){
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return f*x;
}
void init(){
n=read(),L=read();
for(int i=1;i<=n;i++)c[i]=read(),sum[i]=sum[i-1]+c[i];
}
void solve(){
que[r++]=0;
for(int i=1;i<=n;i++){
ll t1=i-1-L+sum[i];
while(r-l>1&&slope(que[l],que[l+1])<2*(double)t1)
l++;
int t2=que[l]+sum[que[l]];
f[i]=f[que[l]]+(t1-t2)*(t1-t2);
while(r-l>1&&slope(que[r-2],que[r-1])>slope(que[r-1],i))
r--;
que[r++]=i;
}
printf("%lld\n",f[n]);
}
int main(){
init();
solve();
return 0;
}