zoukankan      html  css  js  c++  java
  • [HNOI2008]玩具装箱TOY

    洛咕

    题意:(N(N<=50000))件玩具,每件玩具有一个长度(c_i),将玩具分成若干批,如果将第i件玩具到第j个玩具分作一批,那么该批的长度将为(x=j-i+sum_{k=i}^j c_k),每批的代价为((x-L)^2),(L)是一个给定的常数,求最小代价和.

    分析:设(f[i])表示将前i件玩具分成若干批的最小代价,则(f[i]=f[j]+(i-(j+1)+sum[i]-sum[j]-L)^2)

    假设(k<j)且j比k更优,即,

    (f[j]+(i-j-1+sum[i]-sum[j]-L)^2<f[k]+(i-k-1+sum[i]-sum[k]-L)^2)

    (A[i]=i+sum[i]-L-1,g[i]=i+sum[i]),则有

    (f[j]+(A[i]-g[j])^2<f[k]+(A[i]-g[k])^2)

    乱搞一下上式得到,

    (frac{f[j]-g[j]^2-f[k]-g[k]^2}{g[j]-g[k]}<2A[i])

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read(){
       int s=0,w=1;char ch=getchar();
       while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
       while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
       return s*w;
    }
    const int N=50005;
    int a[N],q[N];
    LL sum[N],A[N],g[N],f[N];
    int main(){
        int n=read(),L=read();
        for(int i=1;i<=n;i++){
    		a[i]=read();
    		sum[i]=sum[i-1]+a[i];
    		A[i]=i+sum[i]-L-1;
    		g[i]=i+sum[i];
        }
        int l=1,r=1;q[1]=0;
        memset(f,0x3f,sizeof(f));f[0]=0;
        for(int i=1;i<=n;i++){
    		while(l<r&&(f[q[l+1]]-f[q[l]]+g[q[l+1]]*g[q[l+1]]-g[q[l]]*g[q[l]])<=(2*A[i]*(g[q[l+1]]-g[q[l]])))l++;
    		f[i]=f[q[l]]+(A[i]-g[q[l]])*(A[i]-g[q[l]]);
    		while(l<r&&(f[q[r]]-f[q[r-1]]+g[q[r]]*g[q[r]]-g[q[r-1]]*g[q[r-1]])*(g[i]-g[q[r]])>=(f[i]-f[q[r]]+g[i]*g[i]-g[q[r]]*g[q[r]])*(g[q[r]]-g[q[r-1]]))r--;
    		q[++r]=i;
        }
        printf("%lld
    ",f[n]);
        return 0;
    }
    
    
  • 相关阅读:
    Java Number & Math 类
    excel小技巧-转置(表的横向纵向倒过来)
    excel小技巧-提取填充
    excel小技巧-分列
    Java switch case语句
    if...else
    12.15个人总结
    12.9个人总结
    11.29个人总结
    11.25日个人总结
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11007452.html
Copyright © 2011-2022 走看看