C 牛牛的揠苗助长 二分
链接:https://ac.nowcoder.com/acm/contest/5531/C
思路:二分做法;
check部分的状况即为:
给一个数组,各数值大小随机,每一次操作可以对数组内的
任意一个数进行加一或者减一操作,问最少多少次操作能让这数组内的所有数相等
于是,我们就是找中间位置靠拢,因为有奇数和偶数的情况
当为奇数时,中点位置只有一个,当为偶数时,中点位置有两个
我们直接找出中间的3个点进行枚举即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+10; 5 int a[maxn]; 6 int b[maxn]; 7 int n; 8 int check(ll mid) 9 { 10 ll tmp1=mid/n; 11 for(int i=1;i<=n;i++){ 12 b[i]=a[i]+tmp1; 13 } 14 tmp1=mid%n; 15 for(int i=1;i<=tmp1;i++) b[i]++; 16 sort(b+1,b+1+n); 17 ll basemid=n/2; 18 ll baseleft=basemid-1; 19 ll baseright=basemid+1; 20 ll sum1,sum2,sum3; 21 sum1=sum2=sum3=0; 22 for(int i=1;i<=n;i++){ 23 sum1+=fabs(b[i]-b[basemid]); 24 sum2+=fabs(b[i]-b[baseleft]); 25 sum3+=fabs(b[i]-b[baseright]); 26 } 27 if(sum1<=mid||sum2<=mid||sum3<=mid) return 1; 28 else return 0; 29 } 30 int main() 31 { 32 scanf("%d",&n); 33 for(int i=1;i<=n;i++){ 34 scanf("%d",&a[i]); 35 } 36 ll L=1; ll R=1e18; 37 ll ans; 38 while(L<=R){ 39 ll mid=L+R>>1; 40 if(check(mid)){ 41 ans=mid; 42 R=mid-1; 43 } 44 else L=mid+1; 45 } 46 printf("%lld\n",ans); 47 return 0; 48 }