• [HNOI2008]玩具装箱TOY


    题目描述

    P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过L。但他希望费用最小.

    输入输出格式

    输入格式:

    第一行输入两个整数N,L.接下来N行输入Ci.1<=N<=50000,1<=L,Ci<=10^7

    输出格式:

    输出最小费用

    输入输出样例

    输入样例#1:
    5 4
    3
    4
    2
    1
    4
    输出样例#1:
    1
    dp方程:
    f[i]=f[j]+(i-j-1+s[i]-s[j]-l)^2
    =>f[j]+((i+s[i]-1-l)-(j+s[j]))^2
    =>f[j]+(i+s[i]-1-l)^2+(j+s[j])^2-2(i+s[i]-1-l)*(j+s[j])
    然后就可以斜率优化

    对于i,j比k优时有:j>=k
    f[j]+(i+s[i]-1-l)^2+(j+s[j])^2-2(i+s[i]-1-l)*(j+s[j])
    <=
    f[k]+(i+s[i]-1-l)^2+(k+s[k])^2-2(i+s[i]-1-l)*(k+s[k])
    =>(f[j]+(j+s[j])^2-f[k]-(k+s[k])^2)/2*(j+s[j]-k-s[k])<=(i+s[i]-1-l)

    公式只有右边与i有关,考虑用单调队列,令
    yj=f[j]+(j+s[j])^2,xj=(j+s[j])
    原式=>(yj-yk)/(xj-xk)<=(i+s[i]-1-l)
    令g[k,j]=原式

    首先,不等式成立说明j优于k,由于右边单调递增,所以j以后都优于k,丢掉k
    其次,k<j<i&&g[j,i]<g[k,j]则j可以丢掉
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long lol;
     7 lol l,n,sum[100001];
     8 int head,tail;
     9 lol s[100001],f[100001];
    10 lol X(lol x)
    11 {
    12   lol fm=x+sum[x];
    13   return 2*fm;
    14 }
    15 lol Y(lol x)
    16 {
    17   lol fz=f[x]+(x+sum[x])*(x+sum[x]);
    18   return fz;
    19 }
    20 int main()
    21 {lol i;
    22   cin>>n>>l;
    23   for (i=1;i<=n;i++)
    24     {
    25       scanf("%lld",&sum[i]);
    26       sum[i]+=sum[i-1];
    27     }
    28   head=1;tail=1;
    29   s[1]=0;
    30   for (i=1;i<=n;i++)
    31     {lol j=0;
    32       while (head+1<=tail&&(X(s[head+1])-X(s[head]))*(i+sum[i]-l-1)>=Y(s[head+1])-Y(s[head])) head++;
    33       j=s[head];
    34       //cout<<head<<' '<<tail<<endl;
    35       f[i]=f[j]+(i-j-1+sum[i]-sum[j]-l)*(i-j-1+sum[i]-sum[j]-l);
    36       while (tail-1>=head&&(Y(s[tail])-Y(s[tail-1]))*(X(i)-X(s[tail]))>=(X(s[tail])-X(s[tail-1]))*(Y(i)-Y(s[tail]))) tail--;
    37       tail++;
    38       s[tail]=i;
    39       //cout<<j<<endl;
    40     }
    41   cout<<f[n];
    42 }
  • 相关阅读:
    python023
    python019
    python018
    python017
    python016
    python013
    python012
    数据库,盘它!!!!
    网络编程
    面向对象简述
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7491115.html
Copyright © 2020-2023  润新知