• 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;
    }
  • 相关阅读:
    HDU2586 How far away?(tarjan的LCA)
    You Raise Me Up
    POJ2891 Strange Way to Express Integers(中国剩余定理)
    POJ2142 The Balance(扩展欧几里得)
    HDU 1166模仿大牛写的线段树
    NetWord Dinic
    HDU 1754 线段树裸题
    hdu1394 Minimum Inversion Number
    hdu2795 Billboard
    【完全版】线段树
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10603886.html
Copyright © 2020-2023  润新知