返回顶部

牛客练习赛63 C.牛牛的揠苗助长

  • 题意:有一个长度为\(n\)的数组,从第一天开始,第\(i\)天可以使\(i\)位置上的数\(+1\),当\(i=n\)时,下次从\(i=1\)再开始,另外,在每天结束时,你可以使任意一个位置上的数\(+1\;or\;-1\),或者不变,求最少经过多少天可以使得每个位置上的数都相等.

  • 题解:我们对天数进行二分,由中位数定理:数列中所有数到中位数的距离最小.我们写一个check函数来判断当前天数是否满足条件,\(round\)表示轮数,\(rest\)表示剩下的天数,然后我们记录一个新的\(b\)数组表示所有天数操作完后的值,取中位数为基准,记\(res\)为每天结束后操作的总次数,如果\(res<=x\),则当前的天数满足条件,然后不断二分找一个最小的满足条件的天数即可.

  • 代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #include <unordered_set>
    #include <unordered_map>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<long,long> PLL;
    
    int n;
    ll a[N],b[N];
    
    bool check(ll x){
        int round=x/n;
        int rest=x%n;
        for(int i=1;i<=n;++i){
           b[i]=a[i]+round;
           if(rest){
               b[i]++;
               rest--;
           }
        }
        sort(b+1,b+1+n);
        ll res=0;
        for(int i=1;i<=n;++i){
            res+=abs(b[i]-b[n/2+1]);
        }
        return res<=x;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;++i) cin>>a[i];
        ll l=1,r=1e18;
        while(l<r){
            ll mid=(l+r)>>1;
             if(check(mid)) r=mid;
             else l=mid+1;
        }
        printf("%lld\n",l);
    
        return 0;
    }
    
posted @ 2020-05-09 12:20  _Kolibri  阅读(140)  评论(0)    收藏  举报