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

    Description

      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。但他希望费用最小.

    Input

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

    Output

      输出最小费用

    Sample Input

    5 4
    3
    4
    2
    1
    4

    Sample Output

    1
     
    正解:斜率优化dp
     
    解题报告:我还是太弱了,斜率优化都快忘记了,还是赶紧来复习一下吧
     
    #include <iostream>
    #include <iomanip>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    #define ld long double
    #define RG register
    const int N = 100000;
    
    using namespace std;
    
    int gi(){
        char ch=getchar();int x=0;
        while(ch<'0' || ch>'9') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    
    int f[N],c,head,tail,stack[N];
    ll s[N],dp[N];
    
    ld cmp(int x,int y){
        return (ld)(s[y]*s[y]+2*s[y]*c+dp[y]-s[x]*s[x]-2*s[x]*c-dp[x])*1.0/(2.0*(ld)(s[y]-s[x]));
    }
    
    int main(){
        freopen("toy.in","r",stdin);
        freopen("toy.out","w",stdout);
        int n=gi(),l=gi();
        c=l+1;
        for (RG int i=1; i<=n; ++i) f[i]=gi(),s[i]=s[i-1]+f[i];
        for (RG int i=1; i<=n; ++i) s[i]+=i;
        for (RG int i=1; i<=n; ++i){
            while(head<tail && cmp(stack[head],stack[head+1])<=s[i]) ++head;
            dp[i]=dp[stack[head]]+(s[i]-s[stack[head]]-c)*(s[i]-s[stack[head]]-c);
            while(head<tail && cmp(stack[tail],i)<cmp(stack[tail-1],stack[tail])) --tail;
            stack[++tail]=i;
        }
        printf("%lld
    ",dp[n]);
        return 0;
    }
    

     --------------------------------------------------

    1d1d好像也可以过

    #include <iostream>
    #include <iomanip>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #define RG register
    #define ll long long
    #define File(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    const int N = 100000;
     
    using namespace std;
     
    int gi(){
        char ch=getchar();int x=0;
        while(ch<'0' || ch>'9') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
     
    ll f[N],dp[N];
    int n,s,head,tail;
     
    struct date{
        int l,r,p;
    }stack[N];
     
    ll cal(int i,int v){
        return dp[v]+(f[i]-f[v]+i-v-s)*(f[i]-f[v]+i-v-s);
    }
     
    int find(int l,int r,int i,int p){
        int z=1,y=r,ans=r+1,mid;
        while(z<=y){
            mid=(z+y)>>1;
            if (cal(mid,i)<cal(mid,p)) ans=mid,y=mid-1;
            else z=mid+1;
        }
        return ans;
    }
     
    int main(){
        n=gi(),s=gi()+1,head=1,tail=1;
        for (RG int i=1; i<=n; ++i) f[i]=f[i-1]+gi();
        stack[1]=(date){1,n,0};
        for (RG int i=1; i<=n; ++i){
            while(stack[head].r<i) ++head;
            dp[i]=cal(i,stack[head].p);
            int y=stack[tail].r;
            while(tail>head && stack[tail].l>i && cal(stack[tail].l,i)<cal(stack[tail].l,stack[tail].p)) --tail;
            if (head<=tail){
                int t=find(stack[tail].l,stack[tail].r,i,stack[tail].p);
                if (t<=y){
                    stack[tail].r=t-1;
                    stack[++tail]=(date){t,y,i};
                }
            }
        }
        printf("%lld
    ",dp[n]);
    }
    
  • 相关阅读:
    mysql 数据库备份
    半同步复制
    mysql在线热备
    mysqlxtrabackup备份
    MySQL备份与恢复
    Mysql语句类型
    MySQL的体系结构
    MySQL介绍及安装
    Shell-02-if
    Shell 脚本进阶,经典用法及其案例
  • 原文地址:https://www.cnblogs.com/cjk2001/p/6510471.html
Copyright © 2011-2022 走看看