AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3437
【题解】
f[i]表示前i个牧场被控制的最小代价,sumb表示b数组的前缀和,sumkb表示 b[i]*i 的前缀和
则状态转移方程:f[i]=min{f[j]+a[i]+i*(sumb[i]-sumb[j])-(sumkb[i]-sumkb[j])} (1<=j<i)
设j<k,且从k转移到i比j更优。
得斜率表达式:[(f[j]-sumkb[j])-(f[k]-sumkb[k])]/(sumb[j]-sumb[k])>i
/*************
bzoj 3437
by chty
2016.11.14
*************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
#define FILE "read"
#define MAXN 1000100
#define up(i,j,n) for(ll i=j;i<=n;i++)
namespace INIT{
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline ll read(){
ll x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
}using namespace INIT;
ll n,head,tail,a[MAXN],b[MAXN],sumb[MAXN],sumkb[MAXN],q[MAXN],f[MAXN];
void init(){
n=read();
up(i,1,n) a[i]=read();
up(i,1,n) b[i]=read(),sumb[i]=sumb[i-1]+b[i],sumkb[i]=sumkb[i-1]+b[i]*i;
}
inline double slop(ll j,ll k) {return (double)((f[j]+sumkb[j])-(f[k]+sumkb[k]))/(double)(sumb[j]-sumb[k]);}
void solve(){
up(i,1,n){
while(head<tail&&slop(q[head],q[head+1])<i) head++;
ll t=q[head];
f[i]=f[t]+a[i]+i*(sumb[i]-sumb[t])-(sumkb[i]-sumkb[t]);
while(head<tail&&slop(q[tail-1],q[tail])>slop(q[tail],i)) tail--;
q[++tail]=i;
}
printf("%lld\n",f[n]);
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
init();
solve();
return 0;
}