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
分析
斜率优化傻逼题
仿佛倒着做好写很多,不知道了
代码
#include <bits/stdc++.h>
typedef long long ll;
const int N = 1e6 + 5;
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
int a[N],b[N];
ll sum1[N],sum2[N],dp[N];
ll cal(int head,int tail)
{
return dp[head] + a[tail] + (sum1[tail] - sum1[head]) * tail - (sum2[tail] - sum2[head]);
}
ll up(int head,int tail)
{
return dp[tail] - dp[head] + sum2[tail] - sum2[head];
}
ll down(int head,int tail)
{
return sum1[tail] - sum1[head];
}
int Q[N];
int head = 0, tail = -1;
int main()
{
int 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++)
{
sum1[i] = sum1[i - 1] + b[i];
sum2[i] = sum2[i - 1] + 1ll * b[i] * i;
}
Q[++tail] = 0;
for (int i = 1; i <= n; i++)
{
while (head < tail && up(Q[head], Q[head + 1]) < i * down(Q[head], Q[head + 1]))
++head;
dp[i] = cal(Q[head],i);
while (head < tail && up(Q[tail - 1], Q[tail]) * down(Q[tail], i) >= down(Q[tail - 1], Q[tail]) * up(Q[tail], i))
tail--;
Q[++tail] = i;
}
printf("%lld\n",dp[n]);
}