Codeforces Round #577 (Div. 2) 1201C Maximum Median 前綴和/二分答案

解法一:前綴和+模擬

求增加k之後的最大中位數,必定是在後半段區間進行操作。我們可以很容易想到,先將中間數增大,然後再對後半段區間進行操作使中間數還是中位數,而使an/2還是中位數的話,後面的數仍是升序。
a(n/2)增加到a(n/2)+1,總共需要加(a(n/2)+1-a(n/2)) ×\times 1
a(n/2)增加到a(n/2)+2,總共需要加(a(n/2)+1-a(n/2)) ×\times 1 + (a(n/2)+2-a(n/2)+1)×\times 2
a(n/2)增加到a(n/2)+3,(a(n/2)+1-a(n/2)) ×\times 1 + (a(n/2)+2-a(n/2)+1)×\times 2 + (a(n/2)+3-a(n/2)+2 ×\times 3

依次類推,這就是一個前綴和表達式。因此我們只需要找到k所處的範圍,並進行不能完全增到到a(n/2)+?的處理。時間複雜度O(n)

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
const int MAXN = 2e5 + 10;
long long a[MAXN], b[MAXN];
using namespace std;
typedef long long ll;
int n,k;
int main()
{
	scanf("%d%d", &n, &k);
	_for (i, 0, n) scanf("%d", &a[i]);
	sort(a, a+n);
	int cnt = 0;
	_for (i, n/2+1, n) b[++cnt] = a[i] - a[i - 1];//計算前綴和
    int ans = 0;
    //開始模擬
    _rep (i, 1, cnt) 
    if (k >= ll(b[i] * i)) {k -= b[i]*i; ans += b[i];}//如果k滿足增加到a[(n/2)+i]所需要的花費,那麼中間數則可以增加b[i]
    else {ans += k / i; k = 0;break;}//不能滿足增加到a[(n/2)+i]所需要的花費,從最右端開始一個一個增加,中間數只能加最少的
    if (k)//如果處理完,k還有剩餘。那麼說明中間數已經增加到a[n-1]
    {
        ans += k / (n/2 + 1);
    }
    printf("%d\n", a[n/2] + ans);
}

解法二:二分答案

在這裏插入圖片描述
二分查找最大中位數,模擬增加量與k的關係,判斷是否最大。

#include <bits/stdc++.h>
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
using namespace std;
typedef long long ll;
ll n, k;
ll x;
vector<ll> a;
//模擬x爲中位數需要增加多少moves
bool check(ll x)
{
    ll moves = 0;
    _for (i, n / 2, n)
    {
        if (x - a[i] > 0)  moves += x - a[i];
        if (moves > k) return false;
    }
    if (moves <= k) return true;
    else return false;
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin >> n >> k;
    _for (i, 0, n) {cin >> x; a.push_back(x);}
    sort(a.begin(), a.end());
    ll l = 1, r = 2e10, mid;
    //查找滿足條件的最大值
    while (l != r)
    {
        mid = (l + r + 1) >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    cout << l;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章