[P1419]説明の段落を探している(+単調バイナリキュー)

P1419は、段落求め
ここに画像を挿入説明
つまり、答えの最初の半分を:最大平均の半分。
大きな平均図があれば、我々はすべて、それはsの範囲内で変換インターバル長〜Tが正であるが存在するかどうかを決定する問題であり、半ばを減算します。
プレフィックスとメンテナンスキューと単調。
ここでモノトーンポイントがキューではありません
し、キューが決定単調であるsum[i]-min(sum[i-t]~sum[i-s]),と0を決定することができるよりも大きいです。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ifstream in("input.txt");
ofstream out("output.txt");
#define debug(x) cout<<"# "<<x<<endl
const ll N=100005;
const ll base=137;
const ll mod=2147483647;
const ll INF=1<<30;
ll n,m,a[N],s,t;
double sum[N],ans;

bool check(double mid)
{
    for(int i=1;i<=n;++i)
        sum[i]=sum[i-1]+(double)a[i]-mid;
    ll head=1,tail=0,q[N];
    for(int i=s;i<=n;++i)
    {
        while(head<=tail&&sum[q[tail]]>=sum[i-s])//如果>=说明队列里出现了降序
            tail--;//把最前面的丢掉直到队列保持升序为止
        q[++tail]=i-s;
        //while(!q.empty()&&q.front.index<i-t)q.pop_front();
        while(head<=tail&&q[head]<i-t)//队列里的元素多于最大上限t就pop掉最先进入的值
            head++;
        if(head<=tail&&sum[i]-sum[q[head]]>=0)//如果队列里区间和>=0说明还有更大的平均值(前缀和嘛减后的值就是区间和)
            return 1;
    }
    return 0;
}
int main()
{
    scanf("%lld",&n);
    scanf("%lld %lld",&s,&t);
    for(int i=1;i<=n;++i)
        scanf("%lld",&a[i]);
    double l=-10000.0,r=10000.0;
    while(r - l >= 1e-4)
    {
        double mid=(l+r)/2.0;
        if(check(mid))ans=mid,l=mid;
        else r=mid;
    }
    printf("%.3f\n",ans);
    return 0;
}

公開された77元の記事 ウォン称賛71 ビュー8703

おすすめ

転載: blog.csdn.net/weixin_45697774/article/details/104582688