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=l∑rai≥ans×(r−l+1)
⇒ ∑ i = l r ( a i − a n s ) ≥ 0 \\Rightarrow \\sum\\limits_{i=l}^r (a_i-ans)\\ge 0 ⇒i=l∑r(ai−ans)≥0
令 b i = a i − a n s b_i=a_i-ans bi=ai−ans
我们只需要判断 ∑ 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 寻找段落