洛谷 1404 平均数

【题解】

二分答案

在计算前缀和时减去mid,即s[i]=s[i-1]+a[i]-mid

这样只要有s[i]-s[j]>=0,且i-j>=m,那么mid就是符合条件的

用Min记录s[0]~s[i-m]中最小的s,即可做到O(n)判断

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define LL long long
 4 using namespace std;
 5 const int maxn=200010;
 6 LL n,m,Max,l,r,mid,a[maxn],s[maxn];
 7 void read(LL &k){
 8     k=0; int f=1; char c=getchar();
 9     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
10     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
11     k*=f;
12 }
13 LL min(LL a,LL b){return a>b?b:a;}
14 bool check(LL x){
15     LL Min=Max+1;//Min用来表示s[0]~s[i-m]中最小的s
16     for(int i=1;i<=n;i++){
17         s[i]=s[i-1]+a[i]-x;
18         if(i>=m) Min=min(s[i-m],Min);//更新Min 
19         if(s[i]-Min>=0) return 1; 
20     }
21     return 0;
22 }
23 int main(){
24     read(n); read(m);
25     for(int i=1;i<=n;i++) read(a[i]),a[i]*=1000,Max+=a[i],l=min(a[i],l),r=max(a[i]+1,r);
26     while(l+1<r)if(check(mid=(l+r)>>1)) l=mid; else r=mid;
27     return printf("%lld",l),0;
28 }
View Code
原文地址:https://www.cnblogs.com/DriverLao/p/7994266.html