二分模板(升序顺序)
判断条件的准则:如果想找左边界,就想办法让右边界往左靠;如果想找右边界,就想办法让左边界往右靠
找x的第一个,我们想要右边界不断向左靠近,判定条件为w[mid]在x的右面,即w[mid]>=x,让r=mid
int l=1,r=n;
while(l<r){
int mid=l+r>>1;
if(a[mid]>=x){
r=mid;
}else{
l=mid+1;
}
}
找x的最后一个,我们想要左边界不断向右移动,判定条件为w[mid]在x左面,即w[mid]<=x,让l=mid
int l=1,r=n;
while(l<r){
int mid=l+r+1>>1;
if(a[mid]<=x){
l=mid;
}else{
r=mid-1;
}
}
最佳牛围栏
因为区间长度对于平均值不具有单调性,所以二分枚举平均值avg,如果存在长度不小于F且平均值不小于avg的区间则成立
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const double eps=1e-5;
int n,F;
int w[N];
int maxn;
double sum[N];
bool check(double avg){
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+(w[i]-avg);
}
double minv=0;
for(int i=0,j=F;j<=n;i++,j++){
minv=min(minv,sum[i]);
if(sum[j]-minv>=0) return true;
}
return false;
}
int main(){
cin>>n>>F;
for(int i=1;i<=n;i++){
cin>>w[i];
maxn=max(maxn,w[i]);
}
double l=0,r=maxn;
while(r-l>eps){
double mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
cout<<int(r*1000);
}