加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

codeforce-1201-C题解

发布时间:2020-12-16 09:12:42 所属栏目:百科 来源:网络整理
导读:题目: 给你一个包含n个整数的数组A(n为奇数),对A做k次以下操作: 对数组排序使数组以非递减顺序排列。 选取数组的中位数,然后加一 最终使得数组的中位数最大。 输入:第一行输入两个数字 n 和 k ——数组大小和进行的操作次数 输出:输出最大中位数 栗

题目:给你一个包含n个整数的数组A(n为奇数),对A做k次以下操作:

  • 对数组排序使数组以非递减顺序排列。
  • 选取数组的中位数,然后加一

最终使得数组的中位数最大。

输入:第一行输入两个数字 n 和 k ——数组大小和进行的操作次数

输出:输出最大中位数

栗子:输入  3 2

       1 3 5

   输出  5

(对于这个问题笔者刚开始想的按数组进行二分但是时间复杂度为O(kn)爆了所以更改思路按值进行二分)

思路:?最大中值,那么计算结束数组应该满足--从中间开始到中间后i位的值相等且等于最大中位数。

    首先定义一个的右值(右值应大于数组中的每一个元素,只要大于题目中给的1e9即可),求出其中位数。其次判断此中位数是否满足最大中位数的定义,若是,那么左值为此中位数(要求的是最大中位数)。若不是,那么右值为此中位数减一

?

check函数判断是否满足最大中位数的定义

bool check(ll mid) // 检查mid是否是真正的中值
{
    ll s = 0;
    for (int i = n / 2; i < n; i++) {
        if (mid > A[i])  // A[i] > mid A[i]是不进位的,因为就加不到A[i]那位
            s = s + mid - A[i];
    }
    return (s <= k); // 当s > k时,要成为mid所需要的数比给的数多,则加不到mid那位 所以此mid
}                   //  不是中值   此mid大了 如果小点那么可能就是中值了

然后缩小范围找最大中值

while (l < r) {
        mid = (l + r + 1) / 2;
        if (check(mid))  // 当mid是中值的时候可以选并且继续求大于mid的值是否满中值
            l = mid;
        else
            r = mid - 1;  // mid不是中值的时候说明mid太大了,要往小的调
    }

为什么mid = (l+r+1)/2?因为二分搜索一般用向下取整

详细请参考:https://www.cnblogs.com/flipped/p/4991658.html

完整代码:

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

typedef long long ll;
const int maxn = 200010;
ll n,k,A[maxn];

bool check(ll mid) // 检查mid是否是真正的中值
{
    ll s = 0;
    for (int i = n / 2; i < n; i++) {
        if (mid > A[i])  // A[i] > mid A[i]是不进位的,因为就加不到A[i]那位
            s += mid - A[i];
    }
    return (s <= k); // 当s > k时,要成为mid所需要的数比给的数多,则加不到mid那位 所以此mid
}                 //  不是中值   此mid大了 如果小点那么可能就是中值了

int main()
{
    int i;
    ll l = 0,r = 3e9;
    ll mid;
    scanf_s("%lld%lld",&n,&k);
    for (i = 0; i < n; i++)
        scanf_s("%lld",&A[i]);
    sort(A,A + n);

    while (l < r) {
        mid = (l + r + 1) / 2;
        if (check(mid))  // 当mid是中值的时候可以选并且继续求大于mid的值是否满中值
            l = mid;
        else
            r = mid - 1;  // mid不是中值的时候说明mid太大了,要往小的调
    }
    printf("%lld",l);
    return 0;
}

笔者建议通过逐步运行加上计算的方法理解此题。

?由于笔者才疏学浅,文中难免存在一些错误或疏漏,恳请读者批评指正。

  • 添加到短语集
    ?
    • 没有此单词集: -> 中文(简体)...
      ?
    • 创建新的单词集...
  • 拷贝

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读