zoukankan      html  css  js  c++  java
  • bzoj 3437: 小P的牧场 -- 斜率优化

    3437: 小P的牧场

    Time Limit: 10 Sec  Memory Limit: 128 MB

    Description

    小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被控制)(如果它西边不存在控制站,那么它控制西边所有的牧场),每个牧场被控制都需要一定的花费(毕竟在控制站到牧场间修建道路是需要资源的嘛~),而且该花费等于它到控制它的控制站之间的牧场数目(不包括自身,但包括控制站所在牧场)乘上该牧场的放养量,在第i个牧场建立控制站的花费是ai,每个牧场i的放养量是bi,理所当然,小P需要总花费最小,但是小P的智商有点不够用了,所以这个最小总花费就由你来算出啦。

    Input

    第一行一个整数 n 表示牧场数目

    第二行包括n个整数,第i个整数表示ai

    第三行包括n个整数,第i个整数表示bi

    Output

    只有一行,包括一个整数,表示最小花费

    Sample Input

    4
    2424
    3142

    Sample Output

    9
    样例解释
    选取牧场1,3,4建立控制站,最小费用为2+(2+1*1)+4=9。
    1<=n<=1000000, 0 < a i ,bi < = 10000

    HINT

      设定dp[i]为前在i处放控制台的答案

      那么

        dp[i] = min{ dp[j] + (s[i]-s[j])*i - (c[i]-c[j]) } +a[i]   ,j<i

      其中 s[i] 为 b[i] 的前缀和, c[i] 为 b[i]*i 的前缀和

    #include<map>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 1000100
    #define db double
    char xB[1<<15],*xS=xB,*xTT=xB;
    #define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
    #define isd(c) (c>='0'&&c<='9')
    inline int read(){
        char xchh;
        int xaa;
        while(xchh=getc(),!isd(xchh));(xaa=xchh-'0');
        while(xchh=getc(),isd(xchh))xaa=xaa*10+xchh-'0';return xaa;
    }
    ll c[N],s[N],dp[N],n,a[N],b[N];
    int l,r,q[N],now;
    db cal(int j,int k){return (db)(dp[j]-dp[k]+c[j]-c[k])/(db)(s[j]-s[k]);}
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<=n;i++) b[i]=read();
        for(int i=1;i<=n;i++) s[i]+=s[i-1]+b[i];
        for(int i=1;i<=n;i++) c[i]+=c[i-1]+b[i]*i;
        for(int i=1;i<=n;i++)
        {
            while(l<r&&cal(q[l],q[l+1])<i) l++;
            now=q[l];
            dp[i]=dp[now]+(s[i]-s[now])*i-(c[i]-c[now])+a[i];
            while(l<r&&cal(i,q[r])<cal(q[r],q[r-1])) r--;
            q[++r]=i;
        }
        printf("%lld
    ",dp[n]);
        return 0;
    }

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    电商需求与表结构设计参考
    使用EF操作Oracle数据库小计
    jenkins构建随笔
    NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(转载)
    api接口签名相关文章
    C# 如何防止重放攻击(转载)
    .NET 4中的多线程编程之一:使用Task(转载)
    Flash 无法输入中文的修正方法
    Nape的回调系统 nape.callbacks
    Nape刚体body.align();
  • 原文地址:https://www.cnblogs.com/lkhll/p/6697399.html
Copyright © 2011-2022 走看看