2023牛客暑期多校训练营1 H-Matches

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;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心刍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值