• BZOJ4476 JSOI2015送礼物(分数规划+单调队列)


      看到这个式子当然先二分答案。得max-min-(j-i+k)ans>=0。

      显然max-min相同的情况下所选区间长度越短越好,所以max和min都应该取在边界。那么实际上我们根本不用管端点是否真的是max或min,因为即使不是将他们计入也不会对最终答案造成影响。不妨设右端点是max,则要最大化aj-ai-(j-i)ans=(aj-jans)-(ai-ians),单调队列维护即可。左端点是max同理。

      为了防止不存在长度在l~r的这样的区间,先对长度l的区间单调队列暴力跑一次。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 50010
    const double eps=1E-8;
    int T,n,k,l,r,a[N],p[N],q[N];
    bool check(double ans)
    {
        int head=1,tail=0,head1=1,tail1=0;
        for (int i=1;i<=n;i++)
        {
            while (head<=tail&&p[head]<=i-l) head++;
            while (head<=tail&&a[i]>=a[p[tail]]) tail--;
            p[++tail]=i;
            while (head1<=tail1&&q[head1]<=i-l) head1++;
            while (head1<=tail1&&a[i]<=a[q[tail1]]) tail1--;
            q[++tail1]=i;
            if (i>=l&&a[p[head]]-a[q[head1]]>=(l+k-1)*ans) return 1;
        }
        head=1,tail=0;
        for (int i=1;i<=n;i++)
        {
            while (head<=tail&&q[head]<=i-r) head++;
            if (i>=l)
            {
                while (head<=tail&&a[q[tail]]-q[tail]*ans>=a[i-l+1]-(i-l+1)*ans) tail--;
                q[++tail]=i-l+1;
                if ((a[i]-i*ans)-(a[q[head]]-q[head]*ans)>=k*ans) return 1;
            }
        }
        head=1,tail=0;
        for (int i=1;i<=n;i++)
        {
            while (head<=tail&&q[head]<=i-r) head++;
            if (i>=l)
            {
                while (head<=tail&&a[q[tail]]+q[tail]*ans<=a[i-l+1]+(i-l+1)*ans) tail--;
                q[++tail]=i-l+1;
                if ((a[q[head]]+q[head]*ans)-(a[i]+i*ans)>=k*ans) return 1;
            }
        }
        return 0;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4476.in","r",stdin);
        freopen("bzoj4476.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        T=read();
        while (T--)
        {
            n=read(),k=read(),l=read(),r=read();
            for (int i=1;i<=n;i++) a[i]=read();
            double L=0,R=1000,ans;
            while (L+eps<=R)
            {
                double mid=(L+R)/2;
                if (check(mid)) ans=mid,L=mid+eps;
                else R=mid-eps;
            }
            printf("%.4f
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    flask的简单使用
    Android Studio 使用Lambda表达式
    安卓SDK更新 国内镜像站点记录
    REACT-NATIVE入门(环境搭建及HELLOWORLD)
    深入理解Android 读感(一)
    JNI初入手
    (转)c++ 中的using namespace std是什么意思,什么时候用
    (转)const char to LPCTSTR不能转化问题
    Git常用操作之add操作
    Git日志操作
  • 原文地址:https://www.cnblogs.com/Gloid/p/9879488.html
Copyright © 2020-2023  润新知