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; }