牛牛的揠苗助长(二分)

牛牛的揠苗助长

题目链接

思路

我们考虑最小值的时候通常会考虑二分,但是这道题题目该如何二分呢。

我们知道在时间为\(t\)的范围内我们能改变数组中\(2t\)个值,所以这道题目就是以时间为边界去二分,每当我们经过\(t\)个时间,显然数组中的某一些项会增加。这个时候对数组排一个序,中间的值将会是最优的,也就是\(t\)时间时,需要人为去变换值的基准,然后以这个为基准进行一趟变换,求得人为需要调动的次数,再跟\(t\)进行比较,如果\(调动次数 <= t\)这个时候说明可能存在更优解,更新二分边界\(r = mid\)

代码

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;

ll a[N], b[N];
int n;

bool judge(ll mid) {
    for(int i = 1; i <= n; i++) {
        b[i] = a[i] + mid / n;
        if(mid % n >= i)    b[i]++;
    }
    sort(b + 1, b + 1 + n);
    ll ans = b[n + 1 >> 1], sum = 0;
    for(int i = 1; i <= n; i++)
        sum += llabs(b[i] - ans);
    return sum <= mid;
}

int main() {
    // freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false);
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    ll l = 1, r = 1e18;
    while(l < r) {
        ll mid = l + r >> 1;
        if(judge(mid))  r = mid;
        else    l = mid + 1;
    }
    cout << l << endl;
    return 0;
}
posted @ 2020-05-09 11:09  lifehappy  阅读(157)  评论(0编辑  收藏  举报