H-Matches
题目
Walk Alone has two rows of matches, each of which contains nn matches. He defines the distance between them as d=\sum_{i=1}^n |a_i-b_i|d=∑i=1n∣ai−bi∣, where a_iai and b_ibi represent the height of the ii-th match in the first row and the second row, respectively. Walk Alone wants to beautify the matches by shortening the distance, and you are asked to find out the minimum distance after performing at most one swap within one row. Note that the height can be negative.
题目大意
给定两个长度为n的序列a,b,可以选择其中一个序列交换两个数字,问经过最多一次交换后最小的ai-bi值
思路
将任意两个区间ai和bi的大小关系与以及他们的相交关系进行比较(大概10种情况左右)自己模拟一遍可以发现, 只有当ai<bi,aj>bj,且bj<bi时,对答案是有正贡献的。然后就可以写代码了。
将每一组ai,bi根据大小关系存下来,这里我用0,1来分别表示ai小于/大于bi,将他们存到一个容器后,根据左端点排序,然后可以O(n)的求出最大的交集。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+100;
int n,a[N],b[N];
struct node {
int l,r,p;//p记录a[i],b[i]之间的大小情况
};
vector<node> v;
bool cmp(node x,node y) {
return x.l<y.l;
}
int c[2];
void solve() {
scanf("%d",&n);
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
for(int i=1; i<=n; i++) scanf("%d",&b[i]);
ll sum=0;
for(int i=1; i<=n; i++) {
if(a[i]<b[i]) {
v.push_back((node) {a[i],b[i],0});
}
if(a[i]>b[i]) {
v.push_back((node) {b[i],a[i],1});
}
sum+=abs(a[i]-b[i]);
}
int ans=0;
sort(v.begin(),v.end(),cmp);
c[0]=c[1]=-1e9;
for(node x:v) {
ans=max(ans,min(x.r,c[x.p^1])-x.l);//将已经维护好的另一种情况的最大右端点当前的右端点取小,减去当前左端点,即求在一定选当前区间下可得到的最大交集
c[x.p]=max(c[x.p],x.r);//更新目前为止x.p情况下的最大的右端点
}
printf("%lld",sum-2ll*ans);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--) {
solve();
}
return 0;
}