2019杭电暑期多校第十场 E:Welcome Party(思维)

【题解】

题意: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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值