Maximum Median | 二分 | 本质暴力

参考题解:传送门

题意:一组共有奇数个元素的数列,可以进行k次+1操作(在数列中任意选择数字)问可以生成的最大中位数是多少。

这道题后来看题解看了很久才想明白二分是在干什么。
其实,二分是在暴力的查询所有可能的中位数值,再验证能否在k次内生成。所有可能的中位数数值,最小的必然是原数列不经任何操作的中位数数值,最大的则要根据题目给出的数据范围确定,k最大1e9,数字最大1e9,所以最极端的情况就是这1e9次加法全都加给中位数,那么最大就是2e9(不过这种情况显然是不成立的,因为k全部用尽,这必然不是中位数了)。

所以标程里的一坨二分干的就是这个工作,暴力的找。找完了就要查验了,查验的方法其实也是在暴力。
因为我们要确保这个数是中位数,那么如果它自身进行++,可能会超过后面的数字,一旦超过,就需要给后面的数也++,至少让它们持平,才可以保证我们暴力生成的这些数依然是符合要求的中位数。所以,从中位数的位置往后扫到最后一个,如果比中位数小,就++直到持平。这里面可以使用的总次数就是k。
注意:我们这个for循环是从下标mid开始,因为步骤一里面二分生成中位数也是要消耗k的,我们在上面没有算,在这里一起算。

最后的最后……别忘了sort啊……脑内sort没用的

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

#define MAX_N 200020
#define ll long long

ll n, k, ans, mid;//n个数字(奇数个)的数列 最多进行k次+1操作
ll num[MAX_N];

bool check(ll m)
{
    if(m <= num[mid])
        return 1;

    ll cnt = 0;
    for(int i = mid;i <= n;i++)
    {
        if(num[i] < m)
            cnt += m - num[i];

        if(cnt > k)
            return 0;
    }
    return 1;
}

int main()
{
    scanf("%lld %lld", &n, &k);
    for(int i = 1;i <= n;i++)
        scanf("%lld", &num[i]);

    sort(num+1, num+n+1);

    mid = (n+1)/2;//存储当前的中位数
    ll l = num[mid], r = 2e9+1;


    //下面要枚举所有可能的中位数取值
    while(l <= r)
    {
        ll m = (l+r)/2;
        if(check(m))
        {
            l = m+1;
            ans = m;
        }
        else
            r = m-1;
    }

    printf("%lld\n", ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值