G. Game of Swapping Numbers
题意:
给长度为 n n n的序列 A , B A,B A,B,操作恰好 k k k次交换一组 A i , A j A_i,A_j Ai,Aj,令 ∑ i = 1 n ∣ A i − B i ∣ \sum\limits_{i=1}^{n}|A_i-B_i| i=1∑n∣Ai−Bi∣的值最大。
思路:
很巧妙的一个贪心。
我们其实相当于给
A
,
B
A,B
A,B序列分配相等数量的正负号。
交换相同符号的位置不会影响结果,改变两个符号才会影响结果,将问题变成和序列的顺序无关的情况,只和符号的改变有关。
如果不存在操作次数限制,就相当于将
A
,
B
A,B
A,B放在一起排序,选前
n
n
n个加正号,选后
n
n
n个加负号。
现在现在
k
k
k个,我们将
max
(
a
i
,
b
i
)
\max(a_i,b_i)
max(ai,bi)和
min
(
a
i
,
b
i
)
\min(a_i,b_i)
min(ai,bi)分别排序。
如果存在
min
i
>
max
j
\min_i>\max_j
mini>maxj,那么改变这一对的正负号肯定会令结果变优,会使结果增加
2
×
(
min
i
−
max
j
)
2\times(\min_i-\max_j)
2×(mini−maxj)。
由于我们可以通过交换相同符号的数来消耗次数,所以恰好
k
k
k次可以转换为至多
k
k
k次。
特判
n
=
2
n=2
n=2的情况。
代码:
#include<bits/stdc++.h>
#define int long long
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
const double INF=1e18;
using namespace std;
int a[N],b[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n,k,i;
cin>>n>>k;
for(i=1;i<=n;i++)
cin>>a[i];
for(i=1;i<=n;i++)
cin>>b[i];
if(n==2)
{
if(k&1)
swap(a[1],a[2]);
cout<<abs(a[1]-b[1])+abs(a[2]-b[2])<<endl;
return 0;
}
int sum=0;
for(i=1;i<=n;i++)
{
if(a[i]<b[i])
swap(a[i],b[i]);
sum+=a[i]-b[i];
}
sort(a+1,a+n+1);
sort(b+1,b+n+1,[](int x,int y){
return x>y;
});
for(i=1;i<=n && i<=k;i++)
if(a[i]<b[i])
sum+=2*(b[i]-a[i]);
cout<<sum<<endl;
return 0;
}