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