【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} $$

设决策\(j\)\(k\)优且\(s_0(j) \le s_0(k)\)

$$ \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} $$

由于\(i\)递增,\(s_0(i)\)\(i\)递增而递增,因此我们用单调队列优化

#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;
}

转载于:https://www.cnblogs.com/iwtwiioi/p/4985820.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值