Educational Codeforces Round 75 (Rated for Div. 2) D. Salary Changing(二分答案+贪心)

传送门

题意:
给定n个人的可获得的最低工资,和最高工资,和你的总钱数,保证总钱数能满足所有人的最低工资,现在你要用这些钱去分配工资。问这些人最终获得工资的最大中位数。

思路:
二分答案mid,每一次对答案进行判断。
这里又一点贪心的思想,由于想让答案更大,那么尽量就在不影响答案的情况下花更少的钱,所以我们要提升中位数mid,实际上就只需要将(n/2+1)个人的工资提升到mid。每个人都至少要达到最低工资,所以我们尽量让最低工资大的排在前面,这样额外的花费就会更少。由于每个人都有最高工资,所以只需要加一个if判断一下,mid是否超过了此人的最高工资即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
#define ls (i<<1)
#define rs (i<<1|1)
#define fi first
#define se second
#define mk make_pair
#define mem(a,b) memset(a,b,sizeof(a))
LL read()
{
    LL x=0,t=1;
    char ch;
    while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
    while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
    return x*t;
}
struct node
{
    LL l,r;
};
node a[N];
bool cmp(node p,node q)
{
    return p.l==q.l?p.r>q.r:p.l>q.l;
}
bool judge(LL x,LL n,LL s)
{
    LL res=0;
    LL m=(n>>1)+1;
    for(int i=1;i<=n;i++)
    {
        if(a[i].r>=x&&m)
        {
            res+=max(a[i].l,x);
            m--;
        }
        else res+=a[i].l;
    }
    return res<=s&&!m;
}
int main()
{
    int T=read();
    while(T--)
    {
        LL n=read(),s=read();
        for(int i=1;i<=n;i++)
        {
            a[i].l=read();
            a[i].r=read();
        }
        sort(a+1,a+n+1,cmp);
        LL l=1,r=1e16;
        while(l<=r)
        {
            LL mid=(l+r)>>1;
            if(judge(mid,n,s)) l=mid+1;
            else r=mid-1;
        }
        printf("%lld\n",r);
    }
}
posted @ 2019-12-11 21:14  DeepJay  阅读(75)  评论(0编辑  收藏  举报