arc144B 最大化加减操作后的最小值

给定数组A[i],以及两个数a和b,其中a<=b,每次可以任选一对下标(i,j),让A[i]增加a,同时A[j]减少b,操作次数不限。求能得到的min(A[i])的最大值。

由于每次加得少、减得多,总和必收敛,因此解一定存在,可以二分答案,条件是增加的次数不超过减少的次数。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a; i<=b; i++)
#define per(i,a,b) for(int i=b; i>=a; i--)

const int N = 300005;
int n, a, b, A[N];
int check(int x) {
    int u = 0, v = 0;
    rep(i,1,n) {
        if (A[i] < x) {
            u += (x-A[i]+a-1) / a;
        } else {
            v += (A[i]-x) / b;
        }
    }
    return u <= v;
}
void solve() {
    cin >> n >> a >> b;
    rep(i,1,n) cin >> A[i];
    int lo = 0, hi = 1E10, mid;
    while (lo + 1 < hi) {
        mid = (lo + hi) / 2;
        if (check(mid)) {
            lo = mid;
        } else {
            hi = mid;
        }
    }
    cout << lo << "\n";
}

signed main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}
posted @ 2024-03-11 21:52  chenfy27  阅读(1)  评论(0编辑  收藏  举报