当前位置 : 主页 > 编程语言 > c++ >

codeforce-1201-C题解

来源:互联网 收集:自由互联 发布时间:2021-06-23
题目: 给你一个包含n个整数的数组A(n为奇数),对A做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;
}

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

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

  • 添加到短语集  
    • 没有此单词集: -> 中文(简体)...  
    • 创建新的单词集...
  • 拷贝
上一篇:[CF708C]Centroids
下一篇:P2296-寻找道路
网友评论