码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ】【1010】【HNOI2008】玩具装箱Toy

时间:2015-03-12 19:00:17      阅读:540      评论:0      收藏:0      [点我收藏+]

标签:

DP/斜率优化


  根据题目描述很容易列出动规方程:$$ f[i]=min\{ f[j]+(s[i]-s[j]+i-j-1-L)^2 \}$$

  其中 $$s[i]=\sum_{k=1}^{i} c[k] $$

  而$x$即为$s[i]-s[j]+i-j-1$

  这个$x$的表示实在太不好看,我们容易发现$i-j$其实是可以跟$s[i]-s[j]$合到一起的,即令 $c[i]=c[i]+1$,则$s[i]=\sum_{k=1}^{i} (c[i]+1)=\sum_{k=1}^{i}c[i]+i $,所以$x=s[i]-s[j]-1$。再将那个$-1$与$L$合并,即$L=L+1$,然后我们就得到整理后的方程:$$ f[i]=min\{ f[j]+(s[i]-s[j]-L)^2 \} $$

  证明决策单调性:$( j > k )$

\[ \begin{aligned} f[j]+(s[i]-s[j]-L)^2 &< f[k]+(s[i]-s[k]-L)^2 \\ f[j]-f[k]+(s[j]^2-s[k]^2) &< 2*(s[i]-L)*(s[j]-s[k]) \\ \frac{ f[j]-f[k]+(s[j]^2-s[k]^2) }{ 2*(s[j]-s[k]) } &< s[i]-L \end{aligned} \]

  这里将 $s[i]-L$ 当作一个整体来计算

技术分享
 1 /**************************************************************
 2     Problem: 1010
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:132 ms
 7     Memory:2640 kb
 8 ****************************************************************/
 9  
10 //BZOJ 1010
11 #include<cmath>
12 #include<vector>
13 #include<cstdio>
14 #include<cstring>
15 #include<cstdlib>
16 #include<iostream>
17 #include<algorithm>
18 #define rep(i,n) for(int i=0;i<n;++i)
19 #define F(i,j,n) for(int i=j;i<=n;++i)
20 #define D(i,j,n) for(int i=j;i>=n;--i)
21 #define pb push_back
22 using namespace std;
23 int getint(){
24     int v=0,sign=1; char ch=getchar();
25     while(ch<0||ch>9){ if (ch==-) sign=-1; ch=getchar();}
26     while(ch>=0&&ch<=9){ v=v*10+ch-0; ch=getchar();}
27     return v*=sign;
28 }
29 const int N=50010;
30 typedef long long LL;
31 /******************tamplate*********************/
32 LL c[N],s[N],f[N];
33 int q[N],l,r;
34 double slop(int k,int j){
35     return double(f[j]+s[j]*s[j]-f[k]-s[k]*s[k])/
36         double(2*(s[j]-s[k]));
37 }
38 int main(){
39     int n=getint(),L=getint()+1;
40     F(i,1,n){
41         c[i]=getint()+1;
42         s[i]=s[i-1]+c[i];
43     }
44     F(i,1,n){
45         while(l<r && slop(q[l],q[l+1])<s[i]-L) l++;
46         int t=q[l];
47         f[i]=f[t]+(s[i]-s[t]-L)*(s[i]-s[t]-L);
48         while(l<r && slop(q[r-1],q[r])>slop(q[r],i))r--;
49         q[++r]=i;
50     }
51     printf("%lld\n",f[n]);
52     return 0;
53 }
View Code

 

【BZOJ】【1010】【HNOI2008】玩具装箱Toy

标签:

原文地址:http://www.cnblogs.com/Tunix/p/4332984.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!