主要思路:
我自己的思路,使用结构体然后按a店从大到小排序,然后一个人买的东西从大到小然后从前往后如果选了最大的那第二个人剩下的二分找最接近这个的,后面b店可以随便选,如果遇到大的可以不选b店去选a店。然后在第二个大的此时对应的那个最大的那个b店里的东西是肯定要买的,这时候就要开始考虑了,是否还可以用二分的那个数,然后在二分找到最接近第二大的那个数然后在和之前必须买的最大的数比较然后再找最小值。
看了马哥代码后的思路:a店从小到大排序然后一开始set里面是空的然后,排好序后用b点后缀最大求出每个位置后的最大值,然后是从a点从小遍历就是全买后面的b,然后用后缀最大值剪当前的a,然后st是加可以选择买不买的b店,然后后面在判断二分st里面在a店价值左右两个知否比后缀最大大,大的话就可以在更新最小值。
然后我的思路好像是写起来有点麻烦的,因为对于移除st里面数据的时候还要判断是否后面还有这个数据所以应该是要用mp记录是否次数为0或者得用multiset。
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include<vector>
#include<cstdio>
typedef long long ll;
using namespace std;
struct hh{
ll x,y;
};
int cmp(hh l,hh r){
if(l.x==r.x)return l.y>r.y;
return l.x<r.x;
}
ll pm[5000010];
pair<ll,ll>a[5000010];
void solve(){
set<ll>st;
ll n;
scanf("%lld",&n);
for(int i=1;i<=n;i++){
cin>>a[i].first;
cin>>a[i].second;
//cin>>a[i].x;
//cin>>a[i].y;
}
sort(a+1,a+n+1);
pm[n+1]=-1e18;
st.insert(1e10);
for(int i=n;i>=1;i--){
pm[i]=max(pm[i+1],a[i].second);
}
ll mi=0x3f3f3f3f;
for(int i=1;i<=n;i++){
if(st.size()){
set<ll> :: iterator t;
t=st.lower_bound(a[i].first);
if(*t>=pm[i+1]) mi=min(mi,abs(a[i].first-*t));
t--;
if(*t>=pm[i+1]) mi=min(mi,abs(a[i].first-*t));
}
mi=min(mi,abs(a[i].first-pm[i+1]));
st.insert(a[i].second);
}
cout<<mi<<endl;
}
int main()
{
ll t;
cin>>t;
while (t--)
{
solve();
}
}
这题狂wa30多次所以一定要寄录下来,人麻了。但是也学到一些东西,比如set里面二分函数如果没有比他大的话会返回end()。
这题最后还没a是因为编译器问题,真是人麻了拉黑20版的编译器....