[决策单调性] 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;
}
posted @ 2026-01-12 20:15  Zwi  阅读(2)  评论(0)    收藏  举报