[題解](二分答案/單調隊列)luogu_P1419尋找段落

Posted superminivan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[題解](二分答案/單調隊列)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
",l);
}

 

以上是关于[題解](二分答案/單調隊列)luogu_P1419尋找段落的主要内容,如果未能解决你的问题,请参考以下文章

[題解](最小生成樹)luogu_P2916安慰奶牛

[題解](狀壓/水)luogu_P1879玉米田

[題解]luogu_P1144最短路計數

[題解](水/數學)luogu_P1147連續自然數和

[題解](貪心/堆)luogu_P2107小Z的AK計劃

BZOJ - 2457 思維+貪心