bzoj1010: [HNOI2008]玩具装箱toy

题目
斜率优化dp
原方程 f[i]=min{f[j]+(ij1L+sum[i]sum[j])2} f [ i ] = m i n { f [ j ] + ( i − j − 1 − L + s u m [ i ] − s u m [ j ] ) 2 } <script type="math/tex" id="MathJax-Element-122">f[i]=min{\lbrace f[j]+(i-j-1-L+sum[i]-sum[j])^2\rbrace}</script>
斜率优化后 i+1+L+sum[i]>=f[j]+(j+sum[j])2f[k](k+sum[k])22(j+sum[j]ksum[k]) i + 1 + L + s u m [ i ] >= f [ j ] + ( j + s u m [ j ] ) 2 − f [ k ] − ( k + s u m [ k ] ) 2 2 ( j + s u m [ j ] − k − s u m [ k ] ) <script type="math/tex" id="MathJax-Element-123">i+1+L+sum[i]>=\frac{f[j]+(j+sum[j])^2-f[k]-(k+sum[k])^2}{2(j+sum[j]-k-sum[k])}</script>

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50002;
int n,i,h,t;
ll sum[N],q[N],f[N],L;
ll sqr(ll x){return x*x;}
#define get(i,j) f[j]+sqr(sum[i]-sum[j]+i-j-1-L)
#define up(i,j) (f[i]+sqr(i+sum[i])-f[j]-sqr(j+sum[j]))
#define down(i,j) (i+sum[i]-j-sum[j])*2
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x=0,fl=1;char ch=gc();
    for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
    for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
    return x*fl;
}
int main(){
    n=read();L=read();
    for (i=1;i<=n;i++) sum[i]=read(),sum[i]+=sum[i-1];
    t=1;
    for (i=1;i<=n;i++){
        while (h+1<t && up(q[h+1],q[h])<=down(q[h+1],q[h])*(i-1-L+sum[i])) h++;
        f[i]=get(i,q[h]);
        while (h+1<t && up(i,q[t-1])*down(q[t-1],q[t-2])<=up(q[t-1],q[t-2])*down(i,q[t-1])) t--;
        q[t++]=i;
    }
    printf("%lld",f[n]);
}
posted @ 2018-06-26 11:10  Mingoal  阅读(13)  评论(0)    收藏  举报  来源