1. 程式人生 > >bzoj 1010 [HNOI2008]玩具裝箱toy (斜率優化DP)

bzoj 1010 [HNOI2008]玩具裝箱toy (斜率優化DP)

() etc amp 斜率 sin 維護 lld inline pre

隊列維護下凸包裸題

式子不太好推,但其實不用把式子全展開的.....

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 }

bzoj 1010 [HNOI2008]玩具裝箱toy (斜率優化DP)