[决策单调性] P4767 [IOI2000] 邮局 加强版
posted on 2024-05-28 06:39:40 | under | source
显然,一个邮局的管辖范围是一段区间。感性理解下,非要证明的话对相邻邮局分讨下就好了。
虽然每个村庄对答案贡献为 \(\min\),但答案求的也是 \(\min\),所以去掉村庄的 \(\min\) 不影响最小答案。
于是定义 \(f_{i,j}\) 表示 \(i\) 个邮局,管辖 \([1,j]\) 的最小值。\(f_{i,j}=\min\limits_{0\le k<j}f_{i-1,k}+w(k+1,j)\),\(w(l,r)\) 是在 \([l,r]\) 中放一个邮局的最小花费。
根据初中数学即可 \(O(1)\) 得出 \(w\),所以我们得到 \(O(PV^2)\) 做法。
打表发现 \(f\) 满足决策单调性,证 \(w\) 满足四边形不等式即可。
欲证 \(w(a,b)+w(a+1,b+1)\le w(a,b+1)+w(a+1,b)\)。
具体的话,分奇偶讨论,要算出每个中点,然后计算每段小距离 \(a_i-a_{i-1}\) 被统计多少次,比较即可。这个方法适合手玩。
严格证明是根据 \(w\) 的递推式整出来的(因为区间大小增加 \(1\),中位数不变),不会。
复杂度 \(O(P(P+V))\)。
代码
#include<bits/stdc++.h>
#pragma GCC optimize(3, "Ofast", "inline")
using namespace std;
#define int long long
#define MIN(a, b) a = min(a, b)
const int N = 3e3 + 5, M = 3e2 + 5;
int n, m, a[N], s[N], opt[M][N], f[M][N];
inline int W(int l, int r){
int p = (l + r >> 1);
return a[p] * (p - l + 1) - (s[p] - s[l - 1]) + (s[r] - s[p]) - a[p] * (r - p);
}
signed main(){
cin >> n >> m;
for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]), s[i] = s[i - 1] + a[i];
memset(f, 0x3f, sizeof f), f[0][0] = 0;
for(int i = 1; i <= m; ++i){
opt[i][n + 1] = n;
for(int j = n; ~j; --j)
for(int k = opt[i - 1][j]; k <= min(j - 1, opt[i][j + 1]); ++k)
if(f[i - 1][k] + W(k + 1, j) <= f[i][j]) f[i][j] = f[i - 1][k] + W(k + 1, j), opt[i][j] = k;
}
cout << f[m][n];
return 0;
}

浙公网安备 33010602011771号