# 【BZOJ】3437: 小P的牧场

## 题意

n个点，需要再一些点建立控制站，如果在第$i$个建站，贡献为$a[i]$。假设前一个站为$j<i$，则$[j+1, i]$的点的贡献是$\sum_{k=j+1}^{i} (i-k) b[k]$。同时要求第$n$个点建站。求最小贡献。（$n \le 10^6$

## 题解

$d(i)$表示前$i$个且在第$i$个牧场建控制站的最小贡献

$d(i) = min( d(j) + cost(j+1, i) ) + a[i]$

$ans = d(n)$
$cost(i, j)$表示$[i, j]$$j$控制的费用

\begin{align} cost(i, j) & = \sum_{k=i}^{j} (j-k)b[k] \\ & = j \sum_{k=i}^{j} b[k] - \sum_{k=i}^{j} kb[k] \\ \end{align}

$s_0(n) = \sum_{i=1}^{n} b[i]$
$s_1(n) = \sum_{i=1}^{n} ib[i]$

$cost(i, j) = j (s_0(j) - s_0(i-1)) - (s_1(j) - s_1(i-1))$

\begin{align} d(i) & = min( d(j) + i(s_0(i) - s_0(j)) - s_1(i) + s_1(j) ) \\ & = min( d(j) + s_1(j) - is_0(j) ) + is_0(i) - s_1(i) + a[i] \\ \end{align}

\begin{align} d(j) + s_1(j) - i s_0(j) & \le d(k) + s_1(k) - i s_0(k) \\ d(j) + s_1(j) - ( d(k) + s_1(k) ) & \le i (s_0(j) - s_0(k)) \\ \frac{d(j) + s_1(j) - ( d(k) + s_1(k) )}{ s_0(j) - s_0(k)} & \ge i \\ \end{align}

#include <bits/stdc++.h>
using namespace std;
const int N=1000005;
typedef long long ll;
int a[N], q[N];
ll s0[N], s1[N], d[N];
inline ll Y(int j, int k) {
return d[j]+s1[j]-d[k]-s1[k];
}
inline ll X(int j, int k) {
return (ll)s0[j]-s0[k];
}
int main() {
int n;
scanf("%d", &n);
for(int i=1; i<=n; ++i) {
scanf("%d", &a[i]);
}
for(int i=1; i<=n; ++i) {
scanf("%lld", &s0[i]);
s1[i]=s0[i]*i;
s0[i]+=s0[i-1];
s1[i]+=s1[i-1];
}
int fr=0, ta=1;
q[0]=0;
for(int i=1; i<=n; ++i) {
while(ta-fr>=2 && Y(q[fr], q[fr+1])>(ll)i*X(q[fr], q[fr+1])) {
++fr;
}
int j=q[fr];
d[i]=d[j]+s1[j]-s0[j]*i+s0[i]*i-s1[i]+a[i];
while(ta-fr>=2 && Y(q[ta-2], i)*X(q[ta-2], q[ta-1])<=Y(q[ta-2], q[ta-1])*X(q[ta-2], i)) {
--ta;
}
q[ta++]=i;
}
printf("%lld\n", d[n]);
return 0;
}

posted @ 2015-11-22 14:37  iwtwiioi  阅读(217)  评论(0编辑  收藏  举报