zoukankan      html  css  js  c++  java
  • bzoj4476: [Jsoi2015]送礼物

    考虑二分答案

    对于一个区间一定是一边最大一边最小是最优的,还有不够补足L的情况,这个RMQ就好

    枚举右端点是最大/最小,单调队列搞搞就完了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int _=1e2;
    const int maxn=5e4+_;
    const int mbit=30;
    int n,K,L,R,a[maxn];
    
    namespace ST
    {
        int Bin[mbit],Log[maxn],mx[mbit][maxn],mn[mbit][maxn];
        void main()
        {
            Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2;
            Log[1]=0;for(int i=2;i<=n ;i++)Log[i]=Log[i/2]+1;
            
            for(int i=1;i<=n;i++)mx[0][i]=mn[0][i]=a[i];
            for(int j=1;Bin[j]<=n;j++)
                for(int i=1;i+Bin[j]-1<=n;i++)
                    mx[j][i]=max(mx[j-1][i],mx[j-1][i+Bin[j-1]]),
                    mn[j][i]=min(mn[j-1][i],mn[j-1][i+Bin[j-1]]);
        }
        int mxRMQ(int x,int y)
        {
            int k=Log[y-x+1];
            return max(mx[k][x],mx[k][y-Bin[k]+1]);
        }
        int mnRMQ(int x,int y)
        {
            int k=Log[y-x+1];
            return min(mn[k][x],mn[k][y-Bin[k]+1]);
        }
        double stu1()
        {
            double ans=0;
            for(int j=L;j<=n;j++)
            {
                ans=max(ans,(double)(mxRMQ(j-L+1,j)-mnRMQ(j-L+1,j))/(L-1+K));
            }
            return ans;
        }
    }
    
    namespace DD
    {
        double em;
        namespace A
        {
            struct mnlist//单调减 
            {
                int head,tail,pos[maxn];
                void clear(){head=1,tail=0;}
                void push_back(int x)
                {
                    while(head<=tail&&(double)-a[pos[tail]]<=(double)-a[x]+em*(x-pos[tail]))tail--;
                    pos[++tail]=x;
                }
                void pop_top(int lim){while(head<=tail&&pos[head]<=lim)head++;}
                int top(){return pos[head];}
            }A;
            bool check()
            {
                A.clear();
                for(int j=L;j<=n;j++)
                {
                    A.pop_top(j-R);//<=该决策点无效 
                    A.push_back(j-L+1);
                    
                    int i=A.top();
                    if((double)(a[j]-a[i])+em*i>=em*(K+j))return true;
                }
                return false;
            }
        }
        //~~~~~~~~~~~~~~A~~~~~~~~~~~~~~~~~~~~
        
        namespace B
        {
            struct mxlist
            {
                int head,tail,pos[maxn];
                void clear(){head=1,tail=0;}
                void push_back(int x)
                {
                    while(head<=tail&&(double)a[pos[tail]]<=(double)a[x]+em*(x-pos[tail]))tail--;
                    pos[++tail]=x;
                }
                void pop_top(int lim){while(head<=tail&&pos[head]<=lim)head++;}
                int top(){return pos[head];}
            }B;
            bool check()
            {
                B.clear();
                for(int j=L;j<=n;j++)
                {
                    B.pop_top(j-R);//<=该决策点无效 
                    B.push_back(j-L+1);
                    
                    int i=B.top();
                    if((double)(a[i]-a[j])+em*i>=em*(K+j))return true;
                }    
                return false;
            }
        }
        //~~~~~~~~~~~~~~B~~~~~~~~~~~~~~~~~~~~
        
        bool check(){return A::check()|B::check();}
        double stu2()
        {
            double el=0,er=1e8;
            while(er-el>1e-5)
            {
                em=(el+er)/2;
                if(check())el=em;
                else er=em;
            }
            return el;
        }
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d%d",&n,&K,&L,&R);
            for(int i=1;i<=n;i++)scanf("%d",&a[i]);
            ST::main();
            printf("%.4lf
    ",max(ST::stu1(),DD::stu2()));
        }
        
        return 0;
    }
  • 相关阅读:
    python--Time(时间)模块
    python基础:冒泡和选择排序算法实现
    浅谈python的深浅拷贝
    python随笔--根据号码查询归属地
    python处理字符串:将字符串中的数字相加求和
    Wi-Fi 6解释:下一代Wi-Fi
    Wifi5和Wifi6的区别
    VS Code配置Git环境 X64
    VS Code配置C/C++环境 X64
    MikroTik CCR1036与Tilera GX36处理器
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10603886.html
Copyright © 2011-2022 走看看