题目
输入输出样例
题目大意:
对于数组大小为 n 的两个数组 a,b,在a上进行 k 次交换,使得 ∑i=1n∣ai−bi∣\sum_{i=1}^n{|a_i-b_i|}∑i=1n∣ai−bi∣ 最大。
其实对于绝对值计算,可以等价于为数字加上+,-的符号,例如:aia_iai=3,bib_ibi=1,则|ai−bia_i-b_iai−bi|=+3+(-1)。
先不考虑 k 步交换操作。由于 a 数组时可以交换的,所以题目可以看作是给给 a,b 数组的所有数字分配正负符号,满足正负符号的个数相等的条件下,使得所有数之和最大。
现在考虑 k :
结论:n>2时,恰好 k 步与至多 k 步是等价的
当 n>2 时,a 中一定至少存在两个 + 号或两个 - 号,此时如果我们交换这两个符号对应的数,则并不会使得原问题的解变得更劣,等于是无效操作,只为凑到 k 步。
n=2 需要特殊判断。
贪心思想
我们希望每一步交换都是得到当前最优的值,那么交换 ai,aja_i,a_jai,aj 增加的值能不能量化呢?我们来试一试。
对于 (ai,bi),(aj,bj)(a_i,b_i) , (a_j,b_j)(ai,bi),(aj,bj) ,由于绝对值的存在, ∣ai−bi∣|a_i-b_i|∣ai−bi∣= max(ai,bi)−min(ai,bi)max(a_i,b_i)-min(a_i,b_i)max(ai,bi)−min(ai,bi),所以我们可以对 a,b 数组做交换的操作,使得 a 数组存取较大值,b 数组存取较小值,所以ai>bi,aj>bja_i > b_i , a_j > b_jai>bi,aj>bj 。
接下来只需要讨论 bib_ibi 与 aja_jaj 的大小,即可确定四个数字的大小关系,即可计算增加的值。
当 bi>ajb_i > a_jbi>aj 时:
初始:∣ai−bi∣+∣aj−bj∣=ai+aj−bi−bj|a_i-b_i|+|a_j-b_j|=a_i+a_j-b_i-b_j∣ai−bi∣+∣aj−bj∣=ai+aj−bi−bj
交换后:∣ai−bj∣+∣aj−bi∣=ai+bi−aj−bj|a_i-b_j|+|a_j-b_i|=a_i+b_i-a_j-b_j∣ai−bj∣+∣aj−bi∣=ai+bi−aj−bj
做差为:2∗bi−2∗aj=2∗min(ai,bi))−2∗max(aj,bj))2 * b_i - 2 * a_j=2*min(a_i,b_i))-2 * max(a_j,b_j))2∗bi−2∗aj=2∗min(ai,bi))−2∗max(aj,bj))
当 bi<ajb_i < a_jbi<aj 时:
初始:∣ai−bi∣+∣aj−bj∣=ai+aj−bi−bj|a_i-b_i|+|a_j-b_j|=a_i+a_j-b_i-b_j∣ai−bi∣+∣aj−bj∣=ai+aj−bi−bj
交换后:∣ai−bj∣+∣aj−bi∣=ai+aj−bi−bj|a_i-b_j|+|a_j-b_i|=a_i+a_j-b_i-b_j∣ai−bj∣+∣aj−bi∣=ai+aj−bi−bj
做差为:0(无意义交换)
所以,我们只要取出最大的 k 个 2∗min(ai,bi))−2∗max(aj,bj))2*min(a_i,b_i))-2 * max(a_j,b_j))2∗min(ai,bi))−2∗max(aj,bj)) 即可得到最优值,如果还没有到 k 步差值就小于等于0,那么就可以提前结束了。
代码
#include <bits/stdc++.h>
#include <iostream>
#define ll long long
#define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
using namespace std;
const int MAXN = 5e5 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n,k,ans;
int a[MAXN],b[MAXN];
int main()
{
// freopen("in.txt", "r", stdin);
qc;
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
cin>>b[i];
if(b[i]>a[i])//a[i]中为较大值 b[i]为较小值
swap(b[i],a[i]);
ans+=(a[i]-b[i]);
}
sort(a+1,a+1+n);//从小到大排序
sort(b+1,b+1+n,greater<int>());//从大到小排序
int tmp;
for(int i=1;i<=k&&i<=n;i++)
{
tmp=2*(b[i]-a[i]);//交换的优化:2*(min(a1,b1)-max(a2,b2))
if(tmp>0)
ans+=tmp;
else
break;
}
cout<<ans<<endl;
return 0;
}
碎碎念:
思路很巧妙,但是比赛的时候想不到,orz。一看到交换还有绝对值,就觉得好麻烦,但是没想到这个竟然可以量化计算。