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\n",dp[n]);
    return 0;
}
时间: 2024-10-05 00:12:47

bzoj 3437: 小P的牧场 -- 斜率优化的相关文章

BZOJ 3437 小P的牧场 斜率优化DP

题目大意:有些按照一字排列的牧场,每一个牧场有一个费用和放牧数量.现在要在一些牧场上建造控制站,目的是控制所有的牧场,建立控制站的基础费用就是每个牧场的费用,然后每一个牧场需要付这个牧场的放养数量*它与右边相邻的控制站的距离.求最小的费用. 思路:直接弄有些不好弄,需要两个前缀和来进行差分. sum[i] = Σsrc[i] _sum[i] = Σsrc[i]*i 然后DP方程就是f[i] = f[j] + (sum[i] - sum[j]) * i - _sum[i] + _sum[j] 简单

bzoj3437小P的牧场 斜率优化dp

3437: 小P的牧场 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1542  Solved: 849[Submit][Status][Discuss] Description 小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被

BZOJ3437 小P的牧场(斜率优化dp)

题目link:http://www.lydsy.com/JudgeOnline/problem.php?id=3437; 略略读一下题,发现这题是一道dp 有一些牧场: 1 2 3 4 5 6 7 8 9 10 其中编号大的可以管住编号小的. a[i]表示建站费用 b[i]表示养殖奶牛数目 dp方程大概就出来了 f[i]=min(f[j]+cost(j+1,i)) (0<j<i); 可是有些问题需要O(1)计算cost(j+1,i); 怎么办呢? 于是我想了一个很不清真的计算方法 开了两个数组

【BZOJ3437】小P的牧场 斜率优化 动态规划

呃,老规矩,方程.转化神马的都在代码注释里面. 不会斜率优化的移步这篇:http://blog.csdn.net/vmurder/article/details/41648159 没事闲的想看点经验的来"前一篇"http://blog.csdn.net/vmurder/article/details/41682901 代码: #include <cstdio> #include <cstring> #include <iostream> #inclu

3437: 小P的牧场

3437: 小P的牧场 思路 斜率优化. dp[i]表示到第i个点(第i个点按控制台)的最小代价. 代码 1 #include<cstdio> 2 #include<iostream> 3 4 using namespace std; 5 typedef long long LL; 6 7 const int N = 1000100; 8 LL f[N],s[N],a[N],b[N]; 9 int q[N],L,R; 10 11 inline int read() { 12 int

【BZOJ 1492】 [NOI2007]货币兑换Cash 斜率优化DP

先说一下斜率优化:这是一种经典的dp优化,是OI中利用数形结合的思想解决问题的典范,通常用于优化dp,有时候其他的一些决策优化也会用到,看待他的角度一般有两种,但均将决策看为二维坐标系上的点,并转化为维护凸壳,一种根据两点的斜率与某一常数的大小关系推断二者的优劣,一种将转移方程化为相关直线方程,通过取得最大(小)截距来求最优解.关于其实现方法上,当点的x坐标单调时,可依据比较常数是否单调选择单调队列或单调栈,而当其x坐标不单调时常常使用CDQ分治或平衡树来实现. 千万别用替罪羊来写动态凸壳!!!

BZOJ 1096: [ZJOI2007]仓库建设( dp + 斜率优化 )

dp(v) = min(dp(p)+cost(p,v))+C(v) 设sum(v) = ∑pi(1≤i≤v), cnt(v) = ∑pi*xi(1≤i≤v), 则cost(p,v) = x(v)*(sum(v)-sum(p)) - (cnt(v)-cnt(p)) 假设dp(v)由dp(i)转移比dp(j)转移优(i>j), 那么  dp(i)+cost(i,v) < dp(j)+cost(j,v) 即 dp(i)+x(v)*(sum(v)-sum(i))-(cnt(v)-cnt(i)) <

BZOJ 1096 [ZJOI2007]仓库建设(斜率优化DP)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1096 [题目大意] 有个斜坡,有n个仓库,每个仓库里面都有一些物品,物品数目为p,仓库位置为x,修缮仓库需要的费用为c,现在下雨了,之后修缮的仓库才能放东西,别的地方的仓库要运东西过来,但是只能往比它地势低的运,问所有物品得到保障的最小代价. [题解] 显然可以从高处往低处做DP,dp[i]=min(dp[j]+cost(i,j)) 我们记s[i]为p[i]的前缀和,b[i]为x[i

BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器