牛客练习赛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;
}
I‘m Stein, welcome to my blog