[題解](二分答案/單調隊列)luogu_P1419尋找段落
果然又抄的題解...
顯然答案具有單調性,而對于平均數計算的式子我們移一下項,
若s[l..r]>mid*(r-l+1)无解,
於是我們把每個數都減去一個mid,看和的正負即可,如果為正就可能有更大的平均數,
求子串和最大值可以用單調隊列維護,
#include<bits/stdc++.h> using namespace std; const int maxn=100010; int n,s,t; double a[maxn],sum[maxn]; int b[maxn],q[maxn]; bool check(double x){ int head=1,tail=0; for(int i=1;i<=n;i++) a[i]=(double)b[i]-x; sum[0]=0; for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]; for(int i=1;i<=n;i++){ if(i>=s){//前面不夠長的不處理 while(head<=tail && sum[i-s]<sum[q[tail]])tail--;//如果前綴和較大就彈出 q[++tail]=i-s; } if(head<=tail && q[head]<i-t)head++;//超出右端點 if(head<=tail && sum[i]-sum[q[head]]>=0)return 1;//判斷區間內和是否小於零 } return 0; } int main() { scanf("%d",&n); scanf("%d%d",&s,&t); for(int i=1;i<=n;i++)scanf("%d",&b[i]); double l=-10000,r=10000; while(r-l>1e-5){//多一位精度為了四捨五入 double mid=(l+r)/2; if(check(mid))l=mid; else r=mid; } printf("%.3lf\n",l); }