时间限制: 1500 ms 内存限制: 262144 KB
提交数:174 通过数: 85
【题目描述】
小P有n𝑛 个牧场,自西向东呈一字形排列(自西向东用1…n1…𝑛 编号),为了控制这n𝑛 个牧场,他需要在某些牧场上建立控制站:
每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被控制;如果它西边不存在控制站,那么它控制西边所有的牧场)。
每个牧场被控制都需要一定的花费,而且该花费等于它到控制它的控制站之间的牧场数目(不包括自身,但包括控制站所在牧场)乘上该牧场的放养量。
在第i𝑖个牧场建立控制站的花费是ai𝑎𝑖,每个牧场i的放养量是bi𝑏𝑖。小P 需要总花费最小。
【输入】
第一行一个整数n𝑛 表示牧场数目。
第二行包括n𝑛 个整数,第i𝑖 个整数表示ai𝑎𝑖。
第三行包括n𝑛 个整数,第i𝑖 个整数表示bi𝑏𝑖。
【输出】
只有一行,包括一个整数,表示最小花费。
【输入样例】
4
2 4 2 4
3 1 4 2
【输出样例】
9
【提示】
【样例解释】
选取牧场1、3、41、3、4建立控制站,最小费用为2+(2+1×1)+4=92+(2+1×1)+4=9。
【数据规模及约定】
对于20%的数据 : 1≤n≤101≤𝑛≤10。
对于40%的数据 : 1≤n≤10001≤𝑛≤1000。
对于70%的数据 : 1≤n≤1000001≤𝑛≤100000。
对于100%的数据: 1≤n≤1000000;0<ai,bi≤100001≤𝑛≤1000000;0<𝑎𝑖,𝑏𝑖≤10000。
code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e6+5;
int n;
long long a[MAXN],b[MAXN],B[MAXN];
int stack[MAXN],h,t;
long long f[MAXN];
long long cost(int from,int to){
return to*(b[to]-b[from])-(B[to]-B[from]);
}
double slope(int j,int k){
return (f[j]+B[j]-(f[k]+B[k]))/(b[j]-b[k]);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=n;i++){
scanf("%lld",&b[i]);
B[i]=B[i-1]+b[i]*i;
b[i]+=b[i-1];
}
for(int i=1;i<=n;i++){
while(t>h&&slope(stack[h+1],stack[h])<i)
h++;
f[i]=f[stack[h]]+a[i]+cost(stack[h],i);
while(t>h&&slope(i,stack[t])<slope(stack[t],stack[t-1]))
t--;
stack[++t]=i;
}
cout<<f[n];
return 0;
}