[Ybtoj Chapter 3 Example 3] Maximum mean [two points]

Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here


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(sumisumij+1) ( l < i ≤ n , j ≤ i − l ) (l<i≤n,j≤i−l) (l<in,ji 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 intervalsumij+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);
} 

Guess you like

Origin blog.csdn.net/kejin2019/article/details/112390460
Recommended