D. Salary Changing(找中位数)
题:https://codeforces.com/contest/1251/problem/D
题意:给你n个单位需要满足达到的区间,再给个s,s是要分配给n的单位的量,当然∑l<=s,问经过分配后能够达到的最大中位数是多少
题解:二分找中位数,成立原因:代码注释
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> 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<ll,ll> const int inf=0x3f3f3f3f; const ll INF=1e18; vector<pll>a; 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<a.size();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; }