原题链接
灰太狼养了一群羊,一共有N只羊,每只羊体重为Ai,小羊的生长周期为N,也就是每过N天小羊会长胖一公斤,恰好,每只羊的生长周期错开了,具体来说,第一天第一只羊长胖一公斤,第二天第二只羊长胖一公斤,第n+1天又轮到第一只羊长胖一公斤,
但是红太狼有严重的强迫症!!她想看到所有小羊都是一样重,这样她才能安心挑选羊,所以灰太狼发明了羊羊体重变化器,这个机器每天可以使用一次,效果为:使任意一只小羊,体重增加或者减少一公斤。(当然啦。也可以不进行操作)
问:最短多少天,可以使所有小羊达到相同的体重。
输入:
3
1 2 3
输出
1
HINT
第一天,第一只羊长胖一公斤,并且使用机器使第三只羊减轻一公斤,此时三只羊都是2公斤,所以答案为1天
知识点:二分+点的距离
解法:具备二分的前提:若第d天羊的体重能达到一样,则之后每一天体重都能达到一样(用机器抵消新增体重的羊的重量)。
对于枚举的每个天数d,算出在不使用机器的情况下,每只羊的体重。下一步要求出所有羊体重相等操作机器的最小次数,若该次数<=d,则d是一个合法的答案。
操作机器的次数最少 <==> 将所有羊的的体重增加或减小到羊的体重的中位数(参考:一维坐标下选一个点到给出点的距离和最小)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 100010;
LL a[N], b[N], n, m;
bool check(LL d) {
memcpy(b, a, sizeof b);
for (int i = 0; i < n; i ++) a[i] += d / n;
int mod = d % n;
for (int i = 0; i < mod; i ++) b[i] ++;
sort(b, b + n);
LL need = 0;
for (int i = 0; i < n; i ++) {
need += abs(b[i] - b[n >> 1]);
}
return need <= d;
}
int main() {
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
LL l = 0, r = 1e18;
while (l < r) {
LL mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << l;
return 0;
}