【解题报告】洛谷P1419 寻找段落

【解题报告】洛谷P1419 寻找段落

题目链接

https://www.luogu.com.cn/problem/P1419

思路

这道题目我们首先可以想暴力,我们暴力的时候记录一个前缀和

时间复杂度 \(O(n^2)\)

然后我们考虑优化

我们要找到的是一个最大的平均区间,我们发现,区间长度越小,实际上,得到最大的平均值越大的概率越高,所以我们可以设置一个时间,然后在快要超时的时候直接退出,返回一个暂时的最优解,虽然时间复杂度没改变,还是能通过这一道题目

但是我们当然要正统方法

通过前面的分析可以知道,我们可以二分一个区间的平均值,然后判断这个平均值能不能达到,如果可以达到的话则试更大的平均值,反之,试更小的平均值

然后二分之内的判断函数实际上就是要找是否存在一个序列,使得这个序列的和大于 \(0\)

我们可以使用单调队列来维护是否存在这样一个连续的序列

总共的时间复杂度 \(O(nlogn)\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <ctime>
using namespace std;
const int maxn=100005;
int s,t;
int n;
double a[maxn],b[maxn];
double mx=-1e9;
double ans;
bool check(double x)
{
	for(int i=1;i<=n;i++)
	b[i]=b[i-1]+1.0*a[i]-x;
	int head=1,tail=0;
	int q[maxn];
	for(int i=s,j=0;i<=n;i++,j++)
	{
		while(head<=tail&&b[q[tail]]>b[j]) tail--;
		q[++tail]=j;
		while(head<=tail&&i-q[head]>t) head++; 
		if(b[i]-b[q[head]]>0.00001) return true;
	}
	return false;
}
int main()
{
	cin>>n;
	cin>>s>>t;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		b[i]=b[i-1]+a[i];
		mx=max(mx,1.0*a[i]);
	}
	double l=-10000,r=10000;
	while(l<=r-0.00001)
	{
		double mid=(l+r)/2.0;
		if(check(mid))
		l=mid,ans=l;
		else
		r=mid;
	}
	printf("%.3lf\n",ans);
	return 0;
}
posted @ 2021-10-12 23:54  wweiyi  阅读(77)  评论(0编辑  收藏  举报
js脚本