P1419 寻找段落(二分&单调队列)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1419 寻找段落(二分&单调队列)相关的知识,希望对你有一定的参考价值。

P1419 寻找段落(二分&单调队列)

1.二分答案

2. ∑ i = l r a i ≥ a n s × ( r − l + 1 ) \\sum\\limits_{i=l}^r a_i\\ge ans\\times (r-l+1) i=lraians×(rl+1)

⇒ ∑ i = l r ( a i − a n s ) ≥ 0 \\Rightarrow \\sum\\limits_{i=l}^r (a_i-ans)\\ge 0 i=lr(aians)0

b i = a i − a n s b_i=a_i-ans bi=aians

我们只需要判断 ∑ l e n ∈ [ s , t ] b [ i ] ≥ 0 \\sum\\limits_{len\\in[s,t]}b[i]\\ge 0 len[s,t]b[i]0

即需要维护一个长度在 [ s , t ] [s,t] [s,t]的最大子段和。

所以只需要利用单调队列即可。

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

// Problem: P1419 寻找段落
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1419
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-05-11 10:29:16
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int n,S,T;
double s[N],a[N];
bool ck(double x){
	for(int i=1;i<=n;i++) s[i]=a[i]+s[i-1]-x;
	deque<int>q;
	for(int i=S;i<=n;i++){
		while(!q.empty()&&s[q.back()]>s[i-S]) q.pop_back();
		q.push_back(i-S);
		while(!q.empty()&&q.front()<i-T) q.pop_front();
		if(!q.empty()&&s[i]-s[q.front()]>=0) return true;
	}
	return false;
}
int main(){
	scanf("%d%d%d",&n,&S,&T);
	for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
	double l=-1e4,r=1e4;
	while(r-l>1e-6){
		double m=(l+r)/2;
		if(ck(m)) l=m;
		else r=m;
	}
	printf("%.3f\\n",l);
	return 0;
}

以上是关于P1419 寻找段落(二分&单调队列)的主要内容,如果未能解决你的问题,请参考以下文章

[二分 分数规划 单调队列 最优平均值] P1419 寻找段落

luoguP1419 寻找段落(二分答案+单调队列)

洛谷—— P1419 寻找段落

BZOJ_3316_JC loves Mkk_ 二分答案 + 单调队列

J. Taotao Picks Apples(st&二分)

hdu-3276-dp+二分+单调队列