题目
长度n(n<=2e5)的两个数组a和b,
第i个数分别是ai和bi(1<=ai<=1e9,1<=bi<=1e9)
你可以最多交换一次bi和bj,使得最大
实际t(t<=1e4)组样例,sumn不超过2e5
思路来源
官方题解
题解
赛中没有细想,凭借曼哈顿距离的松弛搞过去了,赛后补一下写法
可以看成是ai<=bi的两条线段,
然后注意到变大的情况只有两条线段交换前不相交,交换后相交
变大的情况只有[min(ai,bi),max(ai,bi)]与[min(aj,bj),max(aj,bj)]不相交时的情况,
而交换端点只有4种情况,两两是等价的,所以只有本质两种情况,
这两种情况都会导致交换后答案变大, 所以可以将a和b交换位置
bonus说要加上a和b的单点修改,那么就维护两个multiset就可以,一个mx的,一个mn的
事实上,二者位置关系共计有12种情况,
分别对应包含、不相交、相交,而这其中4种变大,4种变小,4种不变
代码1(pufanyi代码)
这种是官方题解,注意到只有变大的情况一定是2*(右边区间的左端点-左边区间的右端点)
// Problem: D. Absolute Beauty
// Contest: Codeforces - Codeforces Round 910 (Div. 2)
// URL: https://codeforces.com/contest/1898/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=2e5+10;
int t,n,a[N],b[N],p[4];
ll c[4];
void sol(){
sci(n);
ll ans=0;
rep(i,1,n){
sci(a[i]);
}
rep(i,1,n){
sci(b[i]);
ans+=abs(a[i]-b[i]);
}
int mx=-2e9,mn=2e9;
rep(i,1,n){
mx=max(mx,min(a[i],b[i]));
mn=min(mn,max(a[i],b[i]));
}
ptlle(ans+2ll*max(0,mx-mn));
}
int main(){
sci(t); // t=1
while(t--){
sol();
}
return 0;
}
代码2(superguymj代码)
这种也是基于性质,注意到变大的情况,交换后的终态一定是ai-aj+bi-bj
右边的区间是ai+bi,左边的区间是-aj-bj,
所以分别维护ai+bi的最大值和aj+bj的最小值
// Problem: D. Absolute Beauty
// Contest: Codeforces - Codeforces Round 910 (Div. 2)
// URL: https://codeforces.com/contest/1898/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=2e5+10;
int t,n,a[N],b[N];
ll x[N],y[N],c[N];
ll mx(ll d[]){
ll ans=d[1];
rep(i,2,n)ans=max(ans,d[i]);
return ans;
}
void sol(){
sci(n);
ll ans=0;
rep(i,1,n){
sci(a[i]);
}
rep(i,1,n){
sci(b[i]);
c[i]=abs(a[i]-b[i]);
ans+=c[i];
x[i]=-c[i]+a[i]+b[i];
y[i]=-c[i]-a[i]-b[i];
}
ans+=max(0ll,mx(x)+mx(y));
ptlle(ans);
}
int main(){
sci(t); // t=1
while(t--){
sol();
}
return 0;
}
代码3(曼哈顿距离松弛)
赛中的做法,较第二种更无脑一些,直接4种情况都试一遍取最大
n维曼哈顿距离最大值也是这么做的,
// Problem: D. Absolute Beauty
// Contest: Codeforces - Codeforces Round 910 (Div. 2)
// URL: https://codeforces.com/contest/1898/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=2e5+10;
int t,n,a[N],b[N],p[4];
ll c[4];
void sol(){
sci(n);
ll ans=0;
rep(i,1,n){
sci(a[i]);
}
rep(i,1,n){
sci(b[i]);
ans+=abs(a[i]-b[i]);
}
ll res=ans;
rep(i,0,3)c[i]=1e18;
rep(i,1,n){
rep(j,0,3){
ll v=0,x=abs(a[i]-b[i]);
if(j&1)v-=a[i];
else v+=a[i];
if(j&2)v-=b[i];
else v+=b[i];
if(v+x<c[j])c[j]=v+x;
}
rep(j,0,3){
ll v=0;
if(j&1)v-=a[i];
else v+=a[i];
if(j&2)v-=b[i];
else v+=b[i];
res=max(res,ans-abs(a[i]-b[i])+v-c[j]);
}
}
ptlle(res);
}
int main(){
sci(t); // t=1
while(t--){
sol();
}
return 0;
}