牛牛的揠苗助長(將所有植物對其的最小操作,二分)

2021-10-05 22:02:02 字數 1340 閱讀 2149

題目:牛牛的揠苗助長(牛客)

題目描述(感覺這樣直接貼上不太好):有一塊長度為n(1<=n<=105)的菜地,每塊菜地菜的高度為a[i](i=1,…,n,1<=a[i]<=109)。菜的生長有乙個週期,恰好為n,且第i天a[i%n]菜地長高1。現有魔法每天可使用一次:使某一塊菜地長高或長矮1,或者不變也行。問最少多少天能使所有菜地的菜的高度一樣。

輸入:第一行乙個整數n,第二行n個整數表示a[i]。

輸出:乙個整數,表示需要天數的最小值。

例:輸入:3

1 2 3

輸出:1

分析:乙個經典版本:水稻不會生長,問最少操作。別的不多說,直接上結論:

1).最優策略一定是將所有水稻都向某乙個水稻看齊,也就是至少有一顆水稻是不動的。(特例:如1,6。那麼當x在[a[n/2],a[n/2+1]]範圍內都有最優解,即這裡x在[1,6]範圍內答案都是6,所以也可假設a[1]=1不動)

2).令a[i]不變,ans=(i*a[i]-sum(1,i))+(sum(i+1,n)-(n-i)*a[i])//sum(1,i)表示sum[i]-sum[1-1]即a[i]a[i]的和(sum為字首和陣列,另外別忘了先要對陣列a從小到大排序)。第乙個括號表示將1i項變為a[i]的運算元,第二個括號表示將i+1n項變為a[i]的運算元。然後遍歷i從1n,取最小運算元。複雜度為o(n)。

//這是什麼知識不知,希望下次遇到不會栽。

針對本題(水稻生長怎麼辦):首先無限長時間後我們終於將他們調整到了同一高度,能否保持?能,將每天生長的摁下去不就得了。

也就是說,此問題在答案天數上具有單調性,比如最少ans天,那麼ans+1天也一定能。所以我們二分答案,在已知答案的基礎上計算最少需要的天數是否等於這個答案,等於就ok了。

已經確定了天數,那麼第i科水稻一定生長了ans+(i<=ans%n),每個都加了ans相當於沒加(加了反而會爆掉)。所以ans天時b[i]=a[i]+(i<=ans%n)。然後就當作時水稻不生長的情況就ok。只要最小操作次數<=答案天數,就是合法的。

ac**:

#include

#define ll long long

using namespace std;

const int maxn=100005;

ll a[maxn],b[maxn],sum[maxn];

int n;

ll get_sum(int l,int r)

bool ck(ll days)

return days>=need;

}int main()

else l=mid+1;

}//二分的思想還是很簡單的,也超級有用。感覺就是還有一點點小細節不太懂

cout

}

牛牛的揠苗助長

一眼二分分天數,然後就是要找合適的高度滿足運算元小於天數 兩種方法 二分的check函式裡面三分高度,我們可以發現高度關於運算元是乙個凹函式.要注意臨界值 include using namespace std typedef long long ll const int maxn 1e5 7 ll...

牛客練習賽63 牛牛的揠苗助長 二分)

題目傳送門 牛牛有一塊長度大小為n的菜園,他首先對這塊菜園從1到n進行了編號,每一塊地分別為1號 2號 n號菜地,然後他往每塊菜地中都種下了一些水稻,一開始,第i塊菜地中的水稻高度均為a i 個單位。然後我們知道水稻的生長週期都是n天,也就是說每逢n天水稻就會長高乙個單位。但是不巧的是整個菜園中每一...

牛客5531C 牛牛的揠苗助長 二分 中位數

牛牛有一塊長度大小為n的菜園,他首先對這塊菜園從1到n進行了編號,每一塊地分別為1號 2號 n號菜地,然後他往每塊菜地中都種下了一些水稻,一開始,第i塊菜地中的水稻高度均為a i 個單位。然後我們知道水稻的生長週期都是n天,也就是說每逢n天水稻就會長高乙個單位。但是不巧的是整個菜園中每一塊菜地的生長...