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;
    }

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

  • 相关阅读:
    JS DataURL 整理(一)
    JavaScript 与 ECMAScript 的关系
    HTML5 多媒体之<svg>标签 使用
    HTML5 多媒体之<canvas>标签 使用
    [转]信号量---进程间通信 ---php版
    [转]使用PHP的ftok()函数实现基于linux下系统级进程间消息通信demo(消息队列模式)
    【转】php ftok 使用
    [转]Golang调度模型
    【转】如何分析golang程序的内存使用情况---很有用
    【转】Go 中对栈中函数进行内联---这篇讲的不如上一篇,也还可以吧。。
  • 原文地址:https://www.cnblogs.com/lkhll/p/6697399.html
Copyright © 2011-2022 走看看