看作是一段区间,那么考虑每次交换操作的贡献:

W80xN8.png
k

可以发现两区间无交集无论如何交换都满足其贡献 (事实上,如果令 ,那么 ),而有交集则 ,所以一定是尽量地选择有无集的区间交换。

引理: 时,「操作刚好 次」和「操作不超过 次」是等价的。

证明:将「操作不超过 次」的最优解执行完后,因为 ,根据鸽巢原理, 或者 的情况必然有一个的数量大于等于 ,那么反复交换这两个区间直到达到 次即可。

那么根据引理,将所有 分别从小到大、从大到小 sort 一遍,从前往后扫一遍,当后者大于前者时就将贡献加上,这样做能够使贡献最大化。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<ctime>
#include<cstdlib>
using namespace std;
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
const int N=5e5+10;
int l[N],r[N],x[N],y[N];
int main()
{
    int n=read(),k=read();
    for(int i=1;i<=n;i++)x[i]=read();
    for(int i=1;i<=n;i++)y[i]=read();
    for(int i=1;i<=n;i++)l[i]=min(x[i],y[i]),r[i]=max(x[i],y[i]);
    if(n==2)
    {
        if(k%2)swap(x[1],x[2]);
        printf("%d",abs(x[1]-y[1])+abs(x[2]-y[2]));
    }
    else
    {
        sort(l+1,l+n+1,greater<int>()),sort(r+1,r+n+1);
        ll ans=0;
        for(int i=1;i<=n;i++)ans+=abs(y[i]-x[i]);
        for(int i=1;i<=min(n,k);i++)if(r[i]<l[i])ans+=(l[i]-r[i])*2;
        printf("%lld",ans);
    }
    return 0;
}