• bzoj3437小P的牧场 斜率优化dp


    3437: 小P的牧场

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1542  Solved: 849
    [Submit][Status][Discuss]

    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

     

    Source

    KpmCup#0 By Greens

    正着推和bzoj1096类似 有点麻烦http://www.cnblogs.com/wsy01/p/8119725.html

    我们考虑反着来做 
    假设只在n建立一个控制站 可以算出总花费 sum(b[i]*(n-i))
    然后考虑 减去最多可以节省的花费
    这个最多可以节省的花费可以这样算
    f[i]表示在i建立一个控制站节省的最大代价
    f[i]=f[j]-a[i]-sum[i]*(j-i) j>i
    然后斜率优化。。
    懒得写了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<cstdlib>
     6 #include<algorithm>
     7 #include<queue>
     8 #define ll long long
     9 #define inf 9000000000000000000
    10 #define MAX 1000000000000000000LL
    11 using namespace std;
    12 int read()
    13 {
    14     int x=0,f=1;char ch=getchar();
    15     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    16     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    17     return x*f;
    18 }
    19 int n;
    20 int l=1,r;
    21 ll a[1000005],b[1000005];
    22 int q[1000005];
    23 ll tot,ans,f[1000005],sum[1000005];
    24 double cal(int j,int k)
    25 {
    26     return (double)(f[k]-f[j])/(double)(j-k);
    27 }
    28 int main()
    29 {
    30     n=read();
    31     for(int i=1;i<=n;i++)a[i]=read();
    32     for(int i=1;i<=n;i++)b[i]=read();
    33     for(int i=1;i<=n;i++)sum[i]=sum[i-1]+b[i];
    34     for(int i=1;i<n;i++)
    35         tot+=b[i]*(n-i);
    36     tot+=a[n];
    37     q[++r]=n;
    38     for(int i=n-1;i;i--)
    39     {
    40         while(l<r&&cal(q[l],q[l+1])>sum[i])l++;
    41         int j=q[l];
    42         f[i]=f[j]+sum[i]*(j-i)-a[i];
    43         ans=max(ans,f[i]);
    44         while(l<r&&cal(q[r],i)>cal(q[r-1],q[r]))r--;
    45         q[++r]=i;
    46     }
    47     printf("%lld",tot-ans);
    48     return 0;
    49 }
  • 相关阅读:
    使用接口测试活动的中奖概率(随机事件测试)
    关于测试用例冗余的一些思考
    正则表达式经典实例
    自动化测试断言Assent的使用
    equals与==区别
    Git的使用以及GitHub
    django的配置文件字符串是怎么导入的?
    支付宝支付相关开发
    Django的contenttypes
    推荐课程及用户登录
  • 原文地址:https://www.cnblogs.com/wsy01/p/8127393.html
Copyright © 2020-2023  润新知