解題報告 - 牛客練習賽63 C - 牛牛的揠苗助長(貨倉選址+二分)

鏈接:https://ac.nowcoder.com/acm/contest/5531/C
來源:牛客網

題目描述

牛牛有一塊長度大小爲n的菜園,他首先對這塊菜園從1到n進行了編號,每一塊地分別爲1號、2號…n號菜地,然後他往每塊菜地中都種下了一些水稻,一開始,第i塊菜地中的水稻高度均爲a[i]個單位。然後我們知道水稻的生長週期都是n天,也就是說每逢n天水稻就會長高一個單位。但是不巧的是整個菜園中每一塊菜地的生長週期都錯開了,具體來說,第1天的時候第1塊菜地中的水稻長高一個單位,第2天的時候第2塊菜地中的水稻長高一個單位…第n天的時候第n塊菜地中的水稻長高一個單位,接下來第n+1天,又輪到第1塊菜地中的水稻長高一個單位以此類推。 每天在水稻進行自然生長之後,牛牛可以施展他神奇的魔法,這個魔法可以讓任意一塊菜地中的水稻長高一個單位,或者讓任意一塊菜地中的水稻縮短一個單位,當然啦,他也可以不進行任何操作。 牛牛看到菜園中的水稻參差不齊十分難受,請問至少在第幾天,他能夠讓所有的水稻都長到同一個高度?
輸入描述:
第一行是一個正整數n,1n1051\leq n \leq 10^5,表示有菜園有n塊菜地。接下來一行輸入n個正整數,表示每塊菜地上水稻的高度,水稻的高度1a[i]1091 \leq a[i] \leq 10^9。保證一開始輸入時水稻的高度不全都相同(數據保證答案至少爲1)。
輸出描述:
輸出一個正整數表示問題的答案。

示例1

輸入
3
1 2 3

輸出

1

說明

第一天,第一塊菜地的水稻高度增加1,牛牛使用他的魔法使得第三塊菜地的水稻再減少1。此時三塊水稻的高度爲2 2 2.所有水稻的高度均相同。所以答案爲1天。
題意實際上就是一個求一個時刻,使得當前的序列通過±次數最少 -> 離全部相同的步數最小 -> “貨倉選址” -> 求中位數+二分這個時刻即爲答案

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<vector>

#define ls (p<<1)
#define rs (p<<1|1)
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
#define over(i,s,t) for(register int i = s;i <= t;++i)
#define lver(i,t,s) for(register int i = t;i >= s;--i)
//#define int __int128
#define lowbit(p) p&(-p)
using namespace std;

typedef long long ll;
typedef pair<int,int> PII;

const int N = 1e5+7;
/*題意實際上就是一個求一個時刻,使得當前的序列通過+-次數最少——>離全部相同的步數最小->貨倉選址->求中位數+二分這個時刻即爲答案*/
int n,m;
int a[N],b[N];
bool check(int x){
    ll res = 0;
    over(i,1,n)
    b[i] = a[i]+x/n+(x%n>=i);
    sort(b+1,b+1+n);
    over(i,1,n)
    res += abs(b[i]-b[n/2]);
    return res >x;

}

int main()
{
    scanf("%d",&n);
    over(i,1,n)scanf("%d",&a[i]);
    ll l = 0,r = 1e15+7;
    while(l<r){
        int mid = (l+r)/2;
        if(check(mid))l = mid +1;
        else r = mid;
    }
    printf("%d\n",l);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章