玩具装箱 bzoj1010 斜率优化
斜率优化的题好像都是这样的方程:左边关于j,k的一个(...)/(...)的式子,右边是个只与i有关的可算的数字;
然后把它放到二维坐标轴上,用单调队列维护一个凸壳,O(n)的复杂度;
这道题但是我发现我wrong了,找了程序看了一下,才发现斜率优化还有一点没理解;才明白上午T2能A是由于数据太水,出题人万岁!
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define LL long long 5 const int maxn=50500; 6 LL n,L,a[maxn],g[maxn],q[maxn],tail=0,head=1,f[maxn]; 7 void init(){ 8 freopen("1.in","r",stdin); 9 freopen("1.out","w",stdout); 10 scanf("%d%d",&n,&L); 11 for(int i=1;i<=n;i++){ 12 scanf("%d",&a[i]); 13 g[i]=g[i-1]+a[i]; 14 } 15 } 16 double p(LL k,LL j){ 17 return double(f[j]+g[j]*g[j]-f[k]-g[k]*g[k])/(double)(2*(g[j]-g[k])); 18 } 19 LL squ(LL x){return x*x;} 20 void work(){ 21 for(int i=1;i<=n;i++)g[i]+=i; 22 q[++tail]=0; 23 for(int i=1;i<=n;i++){ 24 while(head<tail&&p(q[head],q[head+1])<g[i]-1-L)head++; 25 cout<<q[head]<<endl; 26 f[i]=f[q[head]]+squ(g[i]-g[q[head]]-L-1); 27 while(head<tail&&p(q[tail],i)<p(q[tail],q[tail-1]))tail--; 28 q[++tail]=i; 29 } 30 cout<<f[n]<<endl; 31 } 32 int main(){ 33 init(); 34 work(); 35 }