题目: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;
}
}