标签:printf 二分答案 mes bool 技术分享 false ++ hide 单调队列
给定一个长度为n的序列a1~an,从中选取一段长度在s到t之间的连续一段使其平均值最大。(n<=100000)
二分答案平均值。
judge时把每一个a[i]-mid得到b[i]
在b[i]中找到一段合法的串使其权值和最大。
当最大权值和大于等于0时则mid上移。
求最大权值和用单调队列就行。(预处理b[i]的前缀和sum[i],队列中记录当前位置可选区间的最小的sum[i])
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdio> using namespace std; const int N=100000; int n,a[N],q[N],s,t; double ans,mid,l,r,sum[N],b[N]; bool judge(double pi){ for(int i=1;i<=n;i++){ b[i]=(double)a[i]-pi; } // cout<<pi<<endl; for(int i=1;i<=n;i++){ sum[i]=sum[i-1]+b[i]; // cout<<sum[i]<<" "; } // cout<<endl; int head=1; int tail=0; for(int i=s;i<=n;i++){ while(q[head]+t-1<i&&head<=tail)head++; while(sum[i-s]<sum[q[tail]]&&head<=tail)tail--; q[++tail]=i-s; if(head<=tail&&sum[i]-sum[q[head]]>=0)return true; } return false; } int main(){ scanf("%d%d%d",&n,&s,&t); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } ans=-10000.0; l=-10000.0;r=10000.0; while(r-l>=1e-5){ mid=(l+r)/2; if(judge(mid)){ ans=mid; l=mid+1e-5; } else r=mid-1e-5; } printf("%.3lf",ans); return 0; }
标签:printf 二分答案 mes bool 技术分享 false ++ hide 单调队列
原文地址:https://www.cnblogs.com/Xu-daxia/p/9414200.html