[題解](二分答案/單調隊列)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);
}

猜你喜欢

转载自www.cnblogs.com/superminivan/p/10732543.html