Problem solving ideas
Obviously, this question needs to divide into two averages. The
question is how to divide the decimal into two?
We can define l, r, midl, r, midl,r,mid 为 d o u b l e double d o u b l e type,
and add aneps epswhen judginge p s is fine. (Eps epse p s is a constant declared in the function program, which controls the accuracy of the iteration, which is equivalent to the infinitesimal value in calculus)
This problem is solved, and we find that there is another problem: to
determine whether the current average of the two points meets the condition is O (n 2) O(n^2)O ( n2 ), it will time out.
First think of prefixes and optimizations.
At this time, the judgment interval ismax (sumi − sumi − j + 1) max(sum_i-sum_(i-j+1))max(sumi−sumi−j+1) ( l < i ≤ n , j ≤ i − l ) (l<i≤n,j≤i−l) (l<i≤n,j≤i − l )
It is not difficult to find that j will only be1 11~ i − l i − l In i − l loop comparison, just max directly, you can save a for loop.
Then pay attention tosumi − j + 1 sum_{i-j+1} in thecurrent intervalsumi−j+1The smallest can get a better answer.
Code
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const double eps=1e-5;
int n,k;
double l,r,mid,sum[200000],a[200000];
bool check(double lyx)
{
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i]-lyx;//求出前缀和(序列和减去mid)
double mann=2147483600,ans=-2147483600;
for(int i=k;i<=n;i++)//省去j的循环
{
mann=min(mann,sum[i-k]);
ans=max(ans,sum[i]-mann);
}
if(ans>=0)return 1;
else return 0;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
l=-1e6,r=1e6;
while(l+eps<r)
{
mid=(l+r)/2;
if(check(mid))
l=mid;
else r=mid;
}
cout<<int(r*1000);
}