【题解】
题意:n个学生分别拥有歌唱能力xi和说相声能力yi,每个人都必须选一个参加,节目的效果等于参加学生中这个才艺最大的能力值,最小化两个界节目的效果差值并输出这个值。
思路:按xi降序排序,从大到小枚举每个值作为歌唱界面的最大值,那么x大于当前值的学生必然要选择说相声,所以我们可以用b记录一定要说相声的能力最大值,那么x小于当前值的学生只有y大于b才有影响答案的可能。我们可以用一个multiset维护当前可选的y值,如果最大的y值都小于a(当前x值),当然前提是大于b,那么答案显然为a-可选最大y值;否则二分寻找大于等于a的y值,更新最优答案,如果这个y值不是最小可选的值那么要判断上一个y值是否能影响答案。
【代码】
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
#define ll long long
struct p{
ll x,y;
}f[maxn];
bool cmp(p a,p b){return a.x>b.x;}
multiset <ll> se;
multiset <ll> ::iterator it;
int main()
{
int T; scanf("%d",&T);
while(T--){
se.clear();
int n; scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lld%lld",&f[i].x,&f[i].y);
se.insert(f[i].y);
}
sort(f,f+n,cmp);
ll ans=(ll)1e18;
ll a,b=-(ll)1e18;
for(int i=0;i<n;i++){
a=f[i].x;
ans=min(ans,abs(a-b));
it=se.lower_bound(f[i].y),se.erase(it);
if(b<a&&!se.empty()){
it=(--se.end());
if(*it>b){
if(*it<a)
ans=min(ans,a-*it);
else{
it=se.lower_bound(a);
ans=min(ans,*it-a);
if(it!=se.begin()&&*(--it)>b) ans=min(ans,abs(a-*it));
}
}
}
b=max(b,f[i].y);
}
printf("%lld\n",ans);
}
return 0;
}