牛客练习赛63 C牛牛的揠苗助长 - 二分

题目
假设有n天,每天,小麦会按照下标依次增长1个单位,第一天第一个小麦长,第二天第二个小麦,第n + 1天第一个小麦长。
牛牛可以在每天操作,使得任意小麦长1单位或减1单位,求最小的n,使得所有小麦都相同长度
首先想到二分,对天数进行二分,然后已知t天,开始对小麦操作
对于cnt = t % n天,是对前cnt个小麦会独自长高1个单位,整体长高t / n个单位,不考虑
那么对于一组数,求最小操作次数,使得每个数字都相同,可以想到对把每个数字变成平均值的次数和,就是最小操作次数
那么先排序,排求出每个数字到平均值的差的绝对值,观察这个值就是牛牛操作的次数,和t天那个大即可
如果牛牛操作的次数小于天数,那么这个天数可行,r = mid,否则,这个天数不行,l = mid + 1

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define ll long long
using namespace std;
const int N = 1e5 + 5;
ll a[N], n;
bool check(ll xx){
    std::vector<ll> v;
    ll cnt = xx % n;
    for(int i = 1; i <= n; i++)
        v.push_back(a[i] + (i <= cnt));
    sort(v.begin(), v.end());

    ll k = v[n / 2], res = 0;
    for(int i = 0; i < n; i++)
        res += abs(v[i] - k);
    return res <= xx;
}
int main(){
    cin >> n;
    ll sum = 0;
    for(int i = 1; i <= n; i++)
        scanf("%lld", &a[i]), sum += a[i];
    ll l = 0, r = 1e14;
    while(l < r){
        ll mid = (l + r) >> 1;
        if(check(mid))r = mid;
        else l = mid + 1;
    }
    cout << l << endl;
    return 0;
}

posted @ 2020-05-08 22:19  Emcikem  阅读(163)  评论(0编辑  收藏  举报