# bzoj3437 小P的牧场

===============================================

f[i]表示在i建个控制站并搞完前i个牧场的最小花费

f[i]=f[j]+sm[j+1]-sm[i]-(sum[i-1]-sum[j])*(n-i)+a[i];

-(n-i)*sum[j]+f[i]=f[j]+sm[j+1]-sm[i]-sum[i-1]*(n-i)+a[i];

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
#define maxn 1010000

int q[maxn];
LL sum[maxn],sm[maxn],f[maxn],a[maxn],b[maxn];
double X(int j){return sum[j];}
double Y(int j){return f[j]+sm[j+1];}
double slop(int j1,int j2){return (Y(j2)-Y(j1))/(X(j2)-X(j1));}
int main()
{
int n,i,l,r;
scanf("%d",&n);sum[0]=0;
memset(f,0,sizeof(f));
for (i=1;i<=n;i++) scanf("%lld",&a[i]);
for (i=1;i<=n;i++)
{
scanf("%lld",&b[i]);
sum[i]=sum[i-1]+b[i];
}sm[n]=0;
for (i=n-1;i>=1;i--) sm[i]+=sm[i+1]+b[i]*(n-i);
l=1;r=1;q[1]=0;
for (i=1;i<=n;i++)
{
while (l<r && slop(q[l],q[l+1])<i-n) l++;
int j=q[l];
f[i]=f[j]+sm[j+1]-sm[i]-(sum[i-1]-sum[j])*(n-i)+a[i];
while (l<r && slop(q[r-1],q[r])>slop(q[r],i)) r--;
q[++r]=i;
}printf("%lld",f[n]);
return 0;
}

posted @ 2016-09-26 19:18  OxQ  阅读(91)  评论(0编辑  收藏  举报