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;
}
posted @ 2019-11-18 13:21  YuhanのBlog  阅读(62)  评论(0编辑  收藏  举报