Loading

P7382 [COCI2018-2019#6] Simfonija (中位数)

P7382 [COCI2018-2019#6] Simfonija

中位数

不妨设 \(C_i=A_i-B_i\),那么操作后的代数式可以写成:

\[\sum\limits_{i=1}^n|C_i+x| \]

如果 \(k=0\),那么 \(x\) 的取值就是一个经典问题了,即 \(C\) 序列的中位数(偶数取中间任意一个)。

如果 \(k\ne 0\),要使答案最小,就是将 \(k\) 个数的代价变为 \(0\)(即将这 \(k\) 个数都取 \(-x\)),然后只需要考虑剩下 \(n-k\) 个数。而这 \(n-k\) 个数在数轴上一定是连续的(可以反证法证明),那么枚举这 \(n-k\) 个数所在位置区间即可。

计算答案预处理前缀和,复杂度 \(O(n)\)

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define mk std::make_pair
#define fi first
#define se second
#define pb push_back

using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5 + 10;
int n, k;
i64 a[N], b[N], c[N], sum[N], ans = linf;
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	std::cin >> n >> k;
	for(int i = 1; i <= n; i++) {
		std::cin >> a[i];
	}
	for(int i = 1; i <= n; i++) {
		std::cin >> b[i];
	}
	for(int i = 1; i <= n; i++) {
		c[i] = a[i] - b[i];
	}
	std::sort(c + 1, c + n + 1);

	for(int i = 1; i <= n; i++) {
		sum[i] = sum[i - 1] + c[i];
	}

	int r = n - k;
	for(int i = r; i <= n; i++) {
		int l = i - r + 1;
		int p = (l + i) >> 1;
		ans = std::min(ans, (p - l) * c[p] - (sum[p - 1] - sum[l - 1]) + (sum[i] - sum[p]) - (i - p) * c[p]);
	}
	std::cout << ans << "\n";

	return 0;
}
posted @ 2024-07-08 18:33  Fire_Raku  阅读(6)  评论(0编辑  收藏  举报