题目链接:点击这里
题目大意:
给定两个长度为
n
n
n 的数组,
a
i
,
b
i
a_i,b_i
ai,bi ,交换
k
k
k 次
a
a
a 中的元素,使得
∑
i
=
1
n
∣
a
i
−
b
i
∣
\sum_{i=1}^n|a_i-b_i|
∑i=1n∣ai−bi∣ 最大,输出该最大值
题目分析:
假设有两对数
(
a
i
,
b
i
)
,
(
a
j
,
b
j
)
(a_i,b_i),(a_j,b_j)
(ai,bi),(aj,bj) ,则不交换使该数对的价值为
∣
a
i
−
b
i
∣
+
∣
a
j
−
b
j
∣
|a_i-b_i|+|a_j-b_j|
∣ai−bi∣+∣aj−bj∣
不妨设
a
i
>
b
i
,
a
j
>
b
j
a_i>b_i,a_j>b_j
ai>bi,aj>bj
若
b
i
>
a
j
b_i>a_j
bi>aj ,交换前为
∣
a
i
−
b
i
∣
+
∣
a
j
−
b
j
∣
=
a
i
+
a
j
−
b
i
−
b
j
|a_i-b_i|+|a_j-b_j|=a_i+a_j-b_i-b_j
∣ai−bi∣+∣aj−bj∣=ai+aj−bi−bj
交换后为
∣
a
j
−
b
i
∣
+
∣
a
i
−
b
j
∣
=
b
i
−
a
j
+
a
i
−
b
j
|a_j-b_i|+|a_i-b_j|=b_i-a_j+a_i-b_j
∣aj−bi∣+∣ai−bj∣=bi−aj+ai−bj ,结果之差为
2
b
i
−
2
a
j
=
2
m
i
n
(
a
i
,
b
i
)
−
2
m
a
x
(
a
j
,
b
j
)
2b_i-2a_j=2min(a_i,b_i)-2max(a_j,b_j)
2bi−2aj=2min(ai,bi)−2max(aj,bj)
若
b
i
<
a
j
b_i<a_j
bi<aj ,交换前为
∣
a
i
−
b
i
∣
+
∣
a
j
−
b
j
∣
=
a
i
+
a
j
−
b
i
−
b
j
|a_i-b_i|+|a_j-b_j|=a_i+a_j-b_i-b_j
∣ai−bi∣+∣aj−bj∣=ai+aj−bi−bj
交换后为
∣
a
j
−
b
i
∣
+
∣
a
i
−
b
j
∣
=
a
j
−
b
i
+
a
i
−
b
j
|a_j-b_i|+|a_i-b_j|=a_j-b_i+a_i-b_j
∣aj−bi∣+∣ai−bj∣=aj−bi+ai−bj ,结果之差为
0
0
0
由此我们发现可以产生贡献的交换是一对数的最小值大于另一对数的最大值的情况。
我们又发现,在
k
=
2
k=2
k=2 时交换情况是唯一的,我们必须把交换次数用完;而
k
>
2
k>2
k>2 时,我们可以选取交换代价为
0
0
0 的组来抵消交换次数,因此在
k
>
2
k>2
k>2 时交换
k
k
k 次是可以转化为交换小于等于
k
k
k 次来处理。
所以在
k
=
2
k=2
k=2 时,我们直接暴力判断结果即可;在
k
>
2
k>2
k>2 时,我们就可以分别把每一对数的最值存下来,然后排个序,贪心的取:让大的最小值和小的最大值交换即可
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#define ll long long
#define inf 0x3f3f3f3f
//#define int ll
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 1e6+5;
//const int mod = 9973;
const double pi = acos(-1);
const double eps = 1e-8;
int n,k,a[maxn],b[maxn],maxx[maxn],minn[maxn];
int main()
{
n = read(),k = read();
for(int i = 1;i <= n;i++) a[i] = read();
for(int i = 1;i <= n;i++) b[i] = read();
ll ans = 0;
if(n == 2)
{
if(k%2) swap(a[1],a[2]);
ans = abs(a[1]-b[1])+abs(a[2]-b[2]);
}
else {
for(int i = 1;i <= n;i++)
{
ans += abs(a[i]-b[i]);
maxx[i] = max(a[i],b[i]);
minn[i] = min(a[i],b[i]);
}
sort(maxx+1,maxx+n+1);
sort(minn+1,minn+n+1,greater<int>());
for(int i = 1;i <= k && i<= n;i++)
if(minn[i] > maxx[i]) ans += 2*(minn[i]-maxx[i]);
else break;
}
cout<<ans<<endl;
return 0;
}