educational codeforces Round 75 D(div2)

题目:http://codeforces.com/contest/1251/problem/D
这个枚举中位数,我们可以排个序,让工人薪资从大到小排序,然后发现可以用二分去做?(有点像跳石头的感觉)但这题的难点在于每一个人的薪资都是一个区间,那我们应该怎么去处理呢(又是一道思维题)?很明显,薪资总共不能超过k,那我们是不是可以,能取中位数的就取中位数,不能取中位数的就给最少的钱(贪心),这样就可以既满足题目要求,又能尽可能满足薪资小于k了。当然check里面还要判断,给大于等于中位数工资的人数有没有大于等于n/2+1个人(还要满足中位数的定义嘛)。
代码还是比较好看的,解释都可以在文字叙述中找到。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
struct node
{
	int l,r;
}a[200005];
int t,n,s;
long long maxx(int a,int b)
{
	if(a>=b)return a;
	else return b; 
}
bool cmp(node a,node b)
{
	if(a.l==b.l)return a.r>b.r;
	return a.l>b.l;
}
bool check(int zhi)
{
	int flag=n/2+1;
	int sum=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i].r>=zhi&&flag)
		{
			flag--;
			sum+=maxx(a[i].l,zhi);
		}
		else
		{
			sum+=a[i].l;
		}
	}
	return sum<=s&&!flag;
}
signed main()
{
	//freopen("123.txt","w",stdout);
	ios::sync_with_stdio(false);
	cin>>t;
	while(t--)
	{
		cin>>n>>s;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i].l>>a[i].r;
		}
		sort(a+1,a+n+1,cmp);
		int l=1,r=s;
		while(l<r)
		{
			int mid=l+r+1>>1;
			if(check(mid))
			{
				l=mid;
			}
			else
			{
				r=mid-1;
			}
		}
		cout<<l<<endl;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章