what the fuck!(二分查找 / 暴力模拟)

what the fuck!

Description

现在有一家公司有nnn个员工(nnn为奇数),他们的工资发放是基本工资+提成,现在这家公司计划再招一批人。要写一篇招聘启事,但是对于这个招聘启事中的薪资具体要写多少犯愁了。

规定招聘启事中薪资为nnn个工人中工资的中位数,为了能更快的招到人,招聘启事中写的薪资越大越好。

现在给出每个人的基本工资,以及可以用来发工资的总钱,你可以自由分配他们的提成(给出的钱可以不用完),让你求出最大的中位数。(保证有答案)

Input

第一行两个整数n,sn,sns。表示有nnn个工人,sss是总的钱数。(1≤n≤2e5,1≤s≤2e121\leq n \leq 2e5,1 \leq s \leq 2e121n2e5,1s2e12)

第二行有nnn个空格隔开的整数,第iii个数字aia_iai表示第iii个人的基本工资。1≤ai≤1e91 \leq a_i \leq 1e91ai1e9

Output

扫描二维码关注公众号,回复: 10242177 查看本文章

一个整数表示最大可能的中位数。

Sample Input 1

5 30
1 2 3 4 5

Sample Output 1

9

Source

lmz

思路

  • 二分思路:对于这题我们把总工资m, 减去基础工资,对基础工资排序后, 那么剩余的钱我们可以合理的发给 后面n/2-1个人,那么前面的那些人是不会影响答案的,我同过二分 n/2-1这个人的工资,看是否有大于等于 n/2-1 人的工资(经过我们分配 钱之后),如果有的话我们继续提高上限,对于在基础工资上分配,我们要遵从贪心的思想,按从基础工资高的人开始分配与 二分工资于这个人的基础工资的 差值

题解一(暴力模拟)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;

#define db double
#define ll long long 

const int Len = 1e6 + 5;
ll sum[Len];
ll ar[Len];

int main()
{
    //freopen("A.txt","r",stdin);
    ll n,m;
    scanf("%lld %lld", &n, &m);
    for(int i = 1; i <= n; i ++)
        scanf("%lld", &ar[i]);
    if(n == 1)
    {
        printf("%lld\n", m + ar[1]);
        return 0;
    }
    sort(ar + 1, ar + 1 + n);

    for(int i = 1; i <= n; i ++)
        sum[i] = sum[i - 1] + ar[i];
    m -= sum[n];

    ll mx = -1;
    int cnt = 1;
    int i;
    for(i = n/2+1; i < n; i ++)
    {
        if((ar[i+1] - ar[i])*cnt <= m)
        {
            mx = ar[i + 1];
            m -= (ar[i+1] - ar[i]) * cnt;
            cnt ++;
        }
        else
            break;
    }
    if(m > 0)
    {
        if(i == n)
            printf("%lld\n", ar[n] + m/(n/2+1));
        else
            printf("%lld\n", ar[n/2 + cnt] + m/(cnt));
    }
    else
        printf("%lld\n", mx == -1 ? ar[n/2+1] : mx);

    return 0;
}

题解二 (二分查找)

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

#define ll long long 
const int Len = 2e5 + 10;
ll ar[Len];
ll n,m;    

bool judge(int mid)
{
    int val =  mid;
    int cnt = 0, mon = m;
    for(int i = n; i >= 1; i --)
    {
        if(ar[i] - val >= 0)
            cnt ++;
        else if(val - ar[i] <= mon)
            cnt ++, mon -= (val - ar[i]);
        else
            break;
        if(cnt >= n/2 + 1) return true;
    }
    return false;
}

int main()
{
    //freopen("A.txt","r",stdin);
    scanf("%lld %lld", &n, &m);
    for(int i = 1; i <= n; i ++)
        scanf("%lld", &ar[i]), m -= ar[i];
    sort(ar + 1, ar + 1 + n);
    ll l = ar[n/2 + 1], r = ar[n] + m;
    ll ans, mid;
    while(l <= r)
    {
        mid = (l + r) >> 1;
        if(judge(mid))
            l = mid + 1, ans = mid;
        else
            r = mid - 1;
    }
    printf("%lld\n", ans);

    return 0;
}
发布了149 篇原创文章 · 获赞 228 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/105152494
今日推荐