P7382 题解
感觉挺奇妙的一道题,思路很巧。
先构造一个数组是给出两个数组的差,再排序,这一点不用多说。
然后我们考虑,要从其中选出 $K$ 个元素修改,那这 $K$ 个元素一定是排序后的数组中两端的元素。
既然这样,那剩下的 $n-K$ 个元素一定是新数组中连续的一段。
于是问题就变成了,在一段数中选择一个数 $x$,使得
$$
\sum_{i=1}^N |A_i-x|$$
最小。由小学奥数得知,这个数应该是这组数的中位数。
至于知道了中位数如何 $O(1)$ 的计算答案,另一篇题解已经讲的很清楚了。
放代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int a[100005],b[100005],cha[100005],n,k,sum[100005],ans,inf=0x3f3f3f3f3f3f3f3f;
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i],cha[i]=a[i]-b[i];
sort(cha+1,cha+n+1);
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+cha[i];
k=n-k,ans=inf;
for(int i=1;i+k-1<=n;i++){
int r=i+k-1;
int mid=(i+r)>>1;
int now=cha[mid]*(mid-i+1)-(sum[mid]-sum[i-1])+(sum[r]-sum[mid])-cha[mid]*(r-mid);
ans=min(ans,now);
}
cout<<ans;
return 0;
}