思路:题目要求
∑
1
≤
i
≤
n
∣
A
i
−
B
i
∣
\sum_{\mathclap{1\le i\le n}} |A_{i}-B_{i}|
1≤i≤n∑∣Ai−Bi∣对换k次b数组元素后,形成的A, B数组会形成n对被减数与减数,最终要求的结果就等于这 n 对的相减之和。
进行被减数与减数的判断:a、b 两个数组内的 2n 个数存入 arr 数组中,以从小到大形式排列,以中间值 arr[cnt / 2] 进行划分,将 a 数组所有的被减数(大于arr[cnt / 2] 的元素)以原来的形式存入 c 数组中,充当减数的以其负数形式存入c数组中,b数组如是此操作存入d数组中。
①先考虑当 n = 2,k若为偶数相当于没变换,结果等于abs(a[1] - b[1])+ abs(a[2] - b[2]),k为奇数则结果等于abs(a[1] - b[2])+ abs(a[2] - b[1])。
②当 k >= n时,这时候一定可以进行被减数与减数的一一配对(k = n),多余的(n-k)操作可以用同为减数或同为被减数的a[ i ]、b[ i ]组合进行消耗。
③当 k < n时,只能进行有限的k次对换操作,且要将结果最大化,进行对换的 b[ i ]、b[ j ]选择满足 a[ i ]、b[ i ]同为被减数,和 a[ j ]、b[ j ]同为减数的两个组合,可以发现对换后,对结果的影响是可以计算的,
Δ
a
n
s
=
2
∗
(
m
i
n
(
a
i
,
b
i
)
−
m
a
x
(
a
j
,
b
j
)
)
\varDelta ans = 2 * (min (ai, bi) - max(aj, bj))
Δans=2∗(min(ai,bi)−max(aj,bj))为了结果最大,我们再用新数组 e 去存同为被减数的a[ i ]、b[ i ]中的较小值,进行从大到小顺序排列,f数组从同为减数的a[ i ]、b[ i ]中较大值,按从小到大顺序排列。for(int i = 1; i <= k; i++) ans = ans + 2 * abs(e[i] - f[i]);
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 10;
int a[maxn], b[maxn], arr[maxn<<1], c[maxn], d[maxn], e[maxn], f[maxn];
inline int abs(int a) { return (a >= 0) ? a : -a; }
#define max(a, b) (a > b) ? a : b
#define min(a, b) (a < b) ? a : b
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int cnt = 1, n, k;
ll ans = 0;
scanf("%d %d", &n, &k);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
arr[cnt++] = a[i];
}
for(int i = 1; i <= n; i++)
{
scanf("%d", &b[i]);
arr[cnt++] = b[i];
ans = ans + 1ll * abs(a[i] - b[i]);
}
cnt--;
if(n == 2)
{
if(k % 2 == 0)
{
cout<<ans<<endl;
}
else
{
ans = abs(a[1] - b[2]) + abs(a[2] - b[1]);
cout<<ans<<endl;
}
return 0;
}
sort(arr+1, arr+cnt+1, greater<int>());
int sign = arr[cnt/2], ccnt = 0;
for(int i = cnt/2; i > 0; i--)
{
if(sign == arr[i])
ccnt++;
if(arr[i] != sign)
break;
}
for(int i = 1; i <= n; i++)
{
if(a[i] > sign)
c[i] = a[i];
else if(a[i] == sign && ccnt > 0)
{
c[i] = a[i];
ccnt--;
}
else c[i] = -a[i];
}
for(int i = 1; i <= n; i++)
{
if(b[i] > sign)
d[i] = b[i];
else if(b[i] == sign && ccnt > 0)
{
d[i] = b[i];
}
else d[i] = -b[i];
}
int fnt = 1, ent = 1;
for(int i = 1; i <= n; i++)
{
if(a[i] == c[i] && b[i] == d[i])
e[ent++] = min(a[i], b[i]);
if(a[i] == -c[i] && b[i] == -d[i])
f[fnt++] = max(a[i], b[i]);
}
ent--;
fnt--;
sort(e+1, e+ent+1, greater<int>());
sort(f+1, f+fnt+1);
int l = min(k, ent);
for(int i = 1; i <= l; i++)
ans = ans + 2ll * (e[i] - f[i]);
cout<<ans<<endl;
return 0;
}