题目描述
小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被控制)(如果它西边不存在控制站,那么它控制西边所有的牧场),每个牧场被控制都需要一定的花费(毕竟在控制站到牧场间修建道路是需要资源的嘛~),而且该花费等于它到控制它的控制站之间的牧场数目(不包括自身,但包括控制站所在牧场)乘上该牧场的放养量,在第i个牧场建立控制站的花费是ai,每个牧场i的放养量是bi,理所当然,小P需要总花费最小,但是小P的智商有点不够用了,所以这个最小总花费就由你来算出啦。
输入输出格式
第一行一个整数 n 表示牧场数目
第二行包括n个整数,第i个整数表示ai
第三行包括n个整数,第i个整数表示bi
只有一行,包括一个整数,表示最小花费
f[i]表示在i建站的最小花费。
f[i]=min(f[j]+∑ik=j+1b[k]∗(i−k)+a[i])
(j<i)
考虑前缀优化
右式可变为
f[j]+∑ik=j+1(b[k]∗i−b[k]∗k)
那么预处理b[j]与b[j]*j前缀
那么该式可变为(b[]为原b[]的前缀和,pre[j]为b[j]*j的前缀和)
f[j]+(b[i]−b[j])∗i−(pre[i]−pre[j])+a[i]
设
j<k
且且k优于j
f[j]+(b[i]−b[j])∗i−(pre[i]−pre[j])+a[i]>f[k]+(b[i]−b[k])∗i−(pre[i]−pre[k])+a[i]
f[j]−b[j]∗i+pre[j]>f[k]−b[k]∗i+pre[k]
(b[k]−b[j])∗i>f[k]−f[j]+pre[k]−pre[j]
i>
f[k]−f[j]+pre[k]−pre[j]b[k]−b[j]
#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
#define fer(i,j,n) for(int i=j;i<=n;i++)
#define far(i,j,n) for(int i=j;i>=n;i--)
const int INF=1e9;
const int maxn=1000010;
using namespace std;
/*----------------------------------------------------*/
inline ll read()
{
char ls;int x=0,sng=1;
for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;
for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
return x*sng;
}
/*----------------------------------------------------*/
ll a[maxn],b[maxn],pre[maxn];
ll f[maxn],q[maxn];
int n;
ll calcK(int j,int k)
{
return (f[k]-f[j]+pre[k]-pre[j])/(b[k]-b[j]);
}
int main()
{
n=read();
memset(b,0,sizeof(b));
memset(pre,0,sizeof(pre));
fer(i,1,n)
a[i]=read();
fer(i,1,n)
{
b[i]=read();
pre[i]=b[i]*i+pre[i-1];
b[i]+=b[i-1];
}
int h=0,t=0;
fer(i,1,n)
{
while(h<t&&calcK(q[h],q[h+1])<i)h++;
f[i]=f[q[h]]+(b[i]-b[q[h]])*i-(pre[i]-pre[q[h]])+a[i];
while(h<t&&calcK(q[t],q[t-1])>calcK(i,q[t]))t--;
q[++t]=i;
}
cout<<f[n];
}