D. Salary Changing(找中位数)

题:https://codeforces.com/contest/1251/problem/D

题意:给你n个单位需要满足达到的区间,再给个s,s是要分配给n的单位的量,当然∑l<=s,问经过分配后能够达到的最大中位数是多少

题解:二分找中位数,成立原因:代码注释

#include
using namespace std;
typedef long long ll;
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=b;i>=a;i--)
#define pb push_back
#define pll pair

const int inf=0x3f3f3f3f;
const ll INF=1e18;
vectora;
int n;
ll s;
ll check(ll m){///挑出能达到中位数midd的都要达到中位数和已经比中位数大的数,且只能取一半+1个 
///因为a 已经按照从大到小排序了,所以从前往后地挑出能达到midd的来加肯定是耗钱最少的 
    int countt=a.size()/2+1;
    ll sum=0;
    for(int i=0;i){
        if(a[i].first<=m&&a[i].second>=m&&countt){
            sum+=m;
            countt--;
        }
        else{
            sum+=a[i].first;
            if(a[i].first>m)
                countt--; 
        }
    }
    if(countt)
        return s+10;//让这一步不合法 
    else
        return sum;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        scanf("%d%I64d",&n,&s);
        a.clear();
        fo(i,1,n){    
            ll x,y;
            scanf("%I64d%I64d",&x,&y);
            a.pb(make_pair(x,y));
        }
        
        sort(a.begin(),a.end());
        reverse(a.begin(),a.end());
        ll l=a[a.size()/2].first+1,r=s;
        while(l<=r){
            ll midd=(l+r)>>1;
            if(check(midd)<=s)
                l=midd+1;
            else
                r=midd-1;
        }
        printf("%I64d\n",l-1);
    }
    return 0;
}
View Code

 

你可能感兴趣的:(D. Salary Changing(找中位数))