BZOJ 1010 [HNOI2008]玩具装箱toy (斜率优化DP)

队列维护下凸包裸题

式子不太好推,但其实不用把式子全展开的.....

k单调递增,x单调递增,队列维护一下就行了

因为f[i]期望最小值,所以维护下凸包

好像记录一下凸包的坐标能减少常数

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #define il inline
 5 #define ll long long
 6 #define N 51000
 7 using namespace std;
 8 int n,que[N];
 9 ll L,f[N],c[N],s[N];
10 int gc()
11 {
12     int rett=0,fh=1;char c=getchar();
13     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
14     while(c>='0'&&c<='9'){rett=(rett<<3)+(rett<<1)+c-'0';c=getchar();}
15     return rett*fh;
16 }
17 il ll yy(ll j){return f[j]+2ll*(s[j]+j)*(1ll+L)+(s[j]+j)*(s[j]+j)+(1ll+L)*(1ll+L);}
18 il ll xx(ll j){return s[j]+j;}
19 il ll kk(ll i){return 2ll*(s[i]+i);}
20 
21 int main()
22 {
23     n=gc(),L=gc();
24     for(int i=1;i<=n;i++) c[i]=gc();
25     for(int i=1;i<=n;i++) s[i]=s[i-1]+c[i];
26     int hd=1,tl=1;
27     for(ll i=1;i<=n;i++)
28     {
29         while(hd+1<=tl&&yy(que[hd])-kk(i)*xx(que[hd])>=yy(que[hd+1])-kk(i)*xx(que[hd+1]))
30             hd++;
31         f[i]=yy(que[hd])-kk(i)*xx(que[hd])+(s[i]+i)*(s[i]+i)-2ll*(s[i]+i)*(1ll+L);
32         while(hd+1<=tl&&(yy(i)-yy(que[tl]))*(xx(que[tl])-xx(que[tl-1])) <= (yy(que[tl])-yy(que[tl-1]))*(xx(i)-xx(que[tl])))
33             tl--;
34         que[++tl]=i;
35     }
36     printf("%lld\n",f[n]);
37     return 0;
38 }

 

posted @ 2018-09-24 22:34  guapisolo  阅读(138)  评论(0编辑  收藏  举报