1. 程式人生 > 實用技巧 >102. 最佳牛圍欄 AcWing

102. 最佳牛圍欄 AcWing

原題連結

字首和+二分答案+雙指標

暴力的思路是:

我們假設mid為答案,先列舉地的數量,列舉區域開始的起始下標,判斷是否有區域的平均值總數大於mid,有就是錯解;

優化:

比較區域平均值大小可以變成假設mid為該區域的平均值,再乘總數作差,如果為負則此答案不正確,這裡可以再優化為求字首和時,每個a[i]都減去mid,再求字首和

當起始座標可以取幾個時,只要有一個符合方案就可返回true

當列舉地數時可以優化為雙指標,雖然i、j在向前移動,可以用變數記錄i的最小值,只要sum[j]>sum[i[說明答案正確

需要注意的是:

因為本道題是向下取整,low與high雖然非常接近,但用low會損失精度,因此用high

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5+10;
 4 const double ep = 1e-6;
 5 int n,f,a[N],sum[N];
 6 bool check(double mid)
 7 {
 8     for(int i=1;i<=n;i++) sum[i] = sum[i-1]-mid;
 9     double minv = 0;
10     for(int i=0,j = f;j<=n;i++,j++){
11         minv = min(sum[i],minv);
12 if(sum[j]>=minv) return true; 13 } 14 return false; 15 } 16 int main() 17 { 18 scanf("%d%d",&n,&f); 19 for(int i=1;i<=n;i++) { scanf("%d",&a[i]);} 20 double low = 1; double high = 2000; 21 while(high-low>ep){ 22 double mid = (low+high)/2;
23 if(check(mid)) low = mid; 24 else high = mid; 25 } 26 printf("%d",(int)high*1000); 27 return 0; 28 }