给定一个序列
ai
,求区间长度在
l
到
二分答案,之后将序列中每一个数减去二分的平均数,原题转换为是否存在一个区间,长度在
l
到
求新的序列的前缀和,记为
bi
则对于每一个
bi
,我们要判断在
bj(i−r≤j≤i−l)
中有没有小于等于
bi
的
那就是一个sliding windows啦
#include<bits/stdc++.h>
using namespace std;
inline int getint(){
int x=0,p=1;
char c=getchar();
while(!isdigit(c)){
if(c=='-')p=-1;
c=getchar();
}
while(isdigit(c)){
x=(x<<3)+(x<<1)+(c^'0');
c=getchar();
}
return x*p;
}
int n,l,r;
double a[100005],b[100005];
inline bool check(double mid){
//cout<<mid<<endl;
for(int i=1;i<=n;++i){
b[i]=a[i]-mid;
}
for(int i=1;i<=n;++i){
b[i]+=b[i-1];
//cout<<b[i]<<" ";
}
//cout<<endl;
deque<int>q;
for(int i=l;i<=n;++i){
while(!q.empty()&&b[q.back()]>b[i-l])q.pop_back();
q.push_back(i-l);
if(b[i]>b[q.front()])return true;
while(!q.empty()&&q.front()<=i-r)q.pop_front();
}
return false;
}
int main(){
n=getint(),l=getint(),r=getint();
for(int i=1;i<=n;++i){
a[i]=getint();
}
double lo=0,hi=1000000;
while(hi-lo>1e-6){
double mid=(hi+lo)/2;
if(check(mid)){
lo=mid;
}
else{
hi=mid;
}
}
printf("%.4f",(lo+hi)/2);
return 0;
}