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 }
View Code

 

posted @ 2020-05-15 17:25  古比  阅读(153)  评论(0编辑  收藏  举报