B. Buying gifts[贪心]

发布时间 2023-09-01 21:25:25作者: qbning

Problem - 1801B - Codeforces

题意是需要给两个人买礼物,有n个商店,每个商店只能给一个人买,而且每个商店给两个人买的礼物的价钱也可能不同,问给两人买的礼物的最大价格之差最小是多少。

我们考虑这种情况。如果当前给b买的礼物最大值为x,那么那些商店里给b礼物价格小于等于x的我们完全可以都买给b,或者部分买给a如果有最优解的话。

既然这样我们按照b的增序进行排序。枚举每一个b。假设此时后面的都买给a(此处类似昨晚D的题解),前面的部分也可以买给a。那么我们就需要搞个后i项最大值。和前i项最接近b的。后面用数组,前面用set维护即可。

注意有些小坑点。

查看代码

#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
ll n;
struct node
{
	int a,b;
}c[500005];
int f[500005];
void solve()
{
	cin>>n;
	int ans=0x7f7f7f7f;
	for(int i=1;i<=n;i++)
		cin>>c[i].a>>c[i].b;
	sort(c+1,c+1+n,[&](node x,node y)->bool{
		if(x.b==y.b)return x.a>y.a;
		return x.b<y.b;
	});
	f[n+1]=0;//这里不加wrong2
	for(int i=n;i>0;i--)
		f[i]=max(c[i].a,f[i+1]);
	set<int>cc;
	for(int i=1;i<=n;i++)
	{
		if(i<n)//这里不加会wrong69
		ans=min(ans,abs(c[i].b-f[i+1]));
		auto it=cc.lower_bound(c[i].b);
		if(it!=cc.end())ans=min(ans,abs(max(*it,f[i+1])-c[i].b));//注意前面最接近b的不一定是a的最大值
		if(it!=cc.begin())--it,ans=min(ans,abs(max(*it,f[i+1])-c[i].b));
		cc.insert(c[i].a);
	}
	cout<<ans<<"\n";
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--)solve();
	return 0;
}