1 #include<cstdio>
 2 #include<iostream>
 3 #define M 50005
 4 using namespace std;
 5 long long sum[M],f[M],n,L,q[M],h,t,C;
 6 double gg(int x,int y)
 7 {
 8    return(f[y]-f[x]+(sum[y]+C)*(sum[y]+C)-(sum[x]+C)*(sum[x]+C))/(2.0*(sum[y]-sum[x]));
 9 }
10 int main()
11 {
12     scanf("%d%d",&n,&L);
13     C=L+1;
14     for(int i=1;i<=n;i++)
15       {
16         int a1;
17         scanf("%d",&a1);
18         sum[i]=sum[i-1]+a1;
19       }
20     for(int i=1;i<=n;i++)
21       sum[i]+=i;
22     h=1;
23     t=1;
24     q[1]=0;
25     for(int i=1;i<=n;i++)
26       {
27         for(;h<t&&gg(q[h],q[h+1])<sum[i];h++);
28         f[i]=f[q[h]]+(sum[i]-sum[q[h]]-C)*(sum[i]-sum[q[h]]-C);
29         for(;h<t&&gg(q[t],i)<gg(q[t-1],q[t]);t--);
30         t++;
31         q[t]=i;
32       }
33     printf("%lld",f[n]);
34 }

这是个斜率优化dp,f[i]=f[j]+(sum[i]-sum[j]+i-j+1-L)^2;

sum数组为前缀和,让sum[i]+=i;C=L-1;

所以f[i]=f[j]+(sum[i]-sum[j]-C)^2;

如果从f[j]转移比从f[k]转移优

即 f[j]+(sum[i]-sum[j]-C)^2<f[k]+(sum[i]-sum[k]-C)^2

化简得  (f[j]-f[k]+(sum[j]+C)*(sum[j]+C)-(sum[k]+C)*(sum[k]+C))/(2*(sum[j]-sum[k]))<sum[i]

这样斜率优化就出去了。

posted on 2016-02-28 06:31  xiyuedong  阅读(151)  评论(0编辑  收藏  举报