1 条题解

  • 0
    @ 2026-4-3 17:58:30

    题目题解

    问题理解

    给定一个长度为 nn(奇数)的数组 aa,每次操作可以将任意元素加 11,最多操作 kk 次。
    求操作后可能的最大中位数。


    第一步:排序

    设排序后的数组为 b1b2bnb_1 \le b_2 \le \dots \le b_n
    中位数是 b(n+1)/2b_{(n+1)/2},即中间元素。
    我们只能通过增加元素来改变中位数,且只影响中间及后面的元素。


    第二步:二分答案

    由于答案具有单调性:若中位数可以达到 xx,则比 xx 小的数也一定可以达到。
    因此可以二分中位数 xx

    对于给定的 xx,我们需要将 b(n+1)/2,b(n+1)/2+1,,bnb_{(n+1)/2}, b_{(n+1)/2+1}, \dots, b_n 中所有小于 xx 的数提升到 xx
    需要的操作次数为:

    $$\text{need}(x) = \sum_{i = (n+1)/2}^{n} \max(0, x - b_i). $$

    need(x)k\text{need}(x) \le k,则 xx 可行;否则不可行。


    第三步:二分范围

    下界:当前中位数 b(n+1)/2b_{(n+1)/2}
    上界:b(n+1)/2+kb_{(n+1)/2} + k(因为最多将中位数增加 kk)。


    第四步:时间复杂度

    • 排序:O(nlogn)O(n \log n)
    • 每次二分检查 O(n/2)=O(n)O(n/2) = O(n)
    • 二分次数 O(log(k))O(log109)30O(\log (k)) \le O(\log 10^9) \approx 30
    • 总复杂度 O(nlogn+nlogk)O(n \log n + n \log k),满足 n2×105n \le 2\times 10^5

    代码实现

    #include <bits/stdc++.h>
    using namespace std;
    
    using ll = long long;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        
        int n, k;
        cin >> n >> k;
        vector<int> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        
        sort(a.begin(), a.end());
        
        int mid = n / 2;  // 中位数下标(0-indexed)
        ll l = a[mid], r = a[mid] + k, ans = a[mid];
        
        while (l <= r) {
            ll x = (l + r) / 2;
            ll need = 0;
            for (int i = mid; i < n; i++) {
                if (a[i] < x) {
                    need += x - a[i];
                    if (need > k) break;
                }
            }
            if (need <= k) {
                ans = x;
                l = x + 1;
            } else {
                r = x - 1;
            }
        }
        
        cout << ans << "\n";
        
        return 0;
    }
    

    验证样例

    输入:

    3 2
    1 3 5
    

    排序后 [1,3,5][1,3,5],中位数下标 11a[1]=3a[1]=3
    二分:

    • x=5x=5,需要 (53)+(55)=22 (5-3)+(5-5)=2 \le 2,可行。
    • x=6x=6,需要 3+1=4>23+1=4 > 2,不可行。
      输出 55

    输入:

    5 5
    1 2 1 1 1
    

    排序后 [1,1,1,1,2][1,1,1,1,2],中位数下标 22a[2]=1a[2]=1
    二分得 x=3x=3,需要 (31)+(31)+(32)=2+2+1=55 (3-1)+(3-1)+(3-2)=2+2+1=5 \le 5,可行。
    输出 33

    输入:

    7 7
    4 1 2 4 3 4 4
    

    排序后 [1,2,3,4,4,4,4][1,2,3,4,4,4,4],中位数下标 33a[3]=4a[3]=4
    二分得 x=5x=5,需要 (54)+(54)+(54)+(54)=1+1+1+1=47 (5-4)+(5-4)+(5-4)+(5-4)=1+1+1+1=4 \le 7,可行。
    输出 55

    与题目输出一致。


    总结

    本题的关键在于:

    1. 排序后,中位数只可能通过增加中间及后面的元素来提升。
    2. 使用二分答案,检查将后半段所有小于 xx 的元素提升到 xx 所需操作数是否 k\le k
    3. 时间复杂度 O(nlogn+nlogk)O(n \log n + n \log k)
    • 1

    信息

    ID
    6344
    时间
    1000ms
    内存
    256MiB
    难度
    2
    标签
    递交数
    1
    已通过
    1
    上传者