pengzhou讲完之后留了几道题......
[HNOI2008]玩具装箱toy
设c[i]是题目中c[i]的前缀和。
手推一下状态转移方程,f[i]=f[k]+(i-k-1+c[i]-c[k]-L)^2
搞一搞,x[k]=k+c[k],y[k]=f[k]+(k+c[k]+l+1)^2
这道题斜率单调递增,用队列维护下凸包即可。
1 #include<cstdio> 2 #define ll long long 3 4 int n,tk=1,pt=1; 5 ll l; 6 ll c[50005]; 7 ll f[50005]; 8 ll q[50005]; 9 10 ll y(int p) 11 { 12 return (ll)(f[p]+(ll)(p+c[p]+l+1)*(ll)(p+c[p]+l+1)); 13 } 14 15 ll x(int p) 16 { 17 return (ll)(p+c[p]); 18 } 19 20 int main() 21 { 22 scanf("%d%lld",&n,&l); 23 for(int i=1;i<=n;i++)scanf("%lld",&c[i]),c[i]+=c[i-1]; 24 for(int i=1;i<=n;i++) 25 { 26 while(tk<pt&&y(q[tk+1])-y(q[tk])<=2ll*(x(i))*(x(q[tk+1])-x(q[tk])))q[tk++]=0; 27 f[i]=f[q[tk]]+((ll)(i-q[tk]-1)+c[i]-c[q[tk]]-l)*((ll)(i-q[tk]-1)+c[i]-c[q[tk]]-l); 28 while(tk<pt&&(y(q[pt])-y(i))*(x(q[pt-1])-x(q[pt]))<=(y(q[pt-1])-y(q[pt]))*(x(q[pt])-x(i)))q[pt--]=0; 29 q[++pt]=i; 30 } 31 printf("%lld",f[n]); 32 }