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\),只需要考虑剩下 \(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;
}
标签:std,int,P7382,sum,中位数,long,2019,Simfonija,define
From: https://www.cnblogs.com/FireRaku/p/18290523