Codeforces 1251D Salary Changing
思路:
1.用pair数组存储每个员工的最小和最大工资,然后进行降序排序;
2.记过程中工资中位数为mid,我们选定一个区间二分查找这个mid;如果所有员工都发放最小工资,那么此刻的mid就应该是所有mid的下界,而总工资S则应该是mid的上界;
3.每次选定一个mid后,我们应该判断这个mid合不合适,判断条件是能找到(n+1)/2个人的工资可以达到mid且总工资不会超过S;至于如何选取这个(n+1)/2个人,排序+贪心就好了;
代码:
#define IOS ios::sync_with_stdio(false)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> P;
#define fi first
#define sc second
#define rp(i,n) for(int i=0;i<n;i++)
#define rpn(i,n) for(int i=1;i<=n;i++)
const int MAX_N=2e5+5;
P emp[MAX_N];
int n,num;
LL s;
bool ok(LL mid){
LL cost=0;
int ans=0;
rp(i,n){
if(emp[i].fi>=mid) ans++;
else if(emp[i].sc>=mid){
cost+=mid-emp[i].fi;
ans++;
}
if(cost>s) return false;
if(ans==num) return true;
}
return false;
}
int main(){
IOS;
int t;
cin>>t;
while(t--){
cin>>n>>s;
num=(n+1)>>1;
rp(i,n) cin>>emp[i].fi>>emp[i].sc;
sort(emp,emp+n,greater<P>());
LL lf=emp[n>>1].fi,rt=s,rs;
rp(i,n) s-=emp[i].fi;
while(rt>=lf){
LL mid=(lf+rt)>>1;
if(ok(mid)){
lf=mid+1;
rs=mid;
}
else rt=mid-1;
}
cout<<rs<<'\n';
}
return 0;
}