[HNOI2008]玩具装箱

link

试题分析

设$dp[i]$表示为去选择第$i$个位最后一个的总价值。复杂度:$O(n^2)$

将$s[i]=\sum_{i=1}^i {c[i]}$,然后$a_i=s_i+i,b_i=s_i+i+1+L$,所以$dp[i]=min{dp[j]+(a[i]-b[j])^2}$

得:$f[j]+b[j]^2=2\times a[i]\times b[j]+f[i]-a[i]^2$

发现$f[j]+b[j]^2$设为$Y$,$2\times a[i]$为斜率,$b[j]$设为$X$,我们发现要求截距最短,即为下凸壳。然后就可以斜率优化了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#define int long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int N=50001;
int Y[N],X[N];
int f[N],s[N],n,L,a[N],b[N],l,r,que[N];
signed main(){ 
    memset(f,127/3,sizeof(f));
    n=read(),L=read();
    for(int i=1;i<=n;i++) s[i]=s[i-1]+read();
    for(int i=0;i<=n;i++) a[i]=s[i]+i,b[i]=s[i]+i+1+L;
    l=1,r=1,que[1]=0,f[0]=0;Y[0]=f[0]+b[0]*b[0],X[0]=b[0]; 
    for(int i=1;i<=n;i++){
        while(l<r&&Y[que[l+1]]-Y[que[l]]<=2*a[i]*(X[que[l+1]]-X[que[l]]))  l++;
        f[i]=f[que[l]]+(a[i]-b[que[l]])*(a[i]-b[que[l]]);
        X[i]=b[i],Y[i]=f[i]+b[i]*b[i];
        while(l<r&&(Y[que[r]]-Y[que[r-1]])*(X[i]-X[que[r]])>=(X[que[r]]-X[que[r-1]])*(Y[i]-Y[que[r]])) r--;
        que[++r]=i;
    }cout<<f[n];
}
View Code

 

posted @ 2018-12-12 16:19  siruiyang_sry  阅读(140)  评论(0编辑  收藏  举报