zoukankan      html  css  js  c++  java
  • 【BZOJ 3316】JC loves Mkk 01分数规划+单调队列

    单调栈
    不断吞入数据维护最值,数据具有单调性但不保证位置为其排名,同时可以按照进入顺序找出临近较值
    单调队列
    队列两端均可删除数据但只有队末可以加入数据,仍然不断吞入数据但同时可以额外刨除一些不符合条件的数据,强调额外刨除数据按照进入顺序,维护在有额外刨除条件下的最值,数据具有单调性但不保证位置为其排名也不保证都是合法,丧失可以按照进入顺序找出临近较值的能力

    #include <cstdio>
    typedef long double ld;
    typedef long long ll;
    const ld eps=1e-8;
    const int N=100010;
    int q[N];
    ld key[N<<1];
    int head,tail;
    int n,L,R;
    int a[N],ans1,ans2;
    inline bool check(ld x){
        for(int i=1;i<=n;++i)
            key[i]=key[i+n]=(ld)a[i]-x;
        for(int i=2;i<=(n<<1);++i)
            key[i]+=key[i-1];
        head=1,tail=0;
        for(int i=L;i<=R;i+=2){
            while(head<=tail&&key[q[tail]]<key[i])tail--;
            q[++tail]=i;
        }
        if(key[q[head]]>0){
            ans1=1,ans2=q[head];
            return true;
        }
        for(int i=3;i<=n;i+=2){
            while(head<=tail&&key[q[tail]]<key[i+R-1])tail--;
            q[++tail]=i+R-1;
            while(head<=tail&&q[head]<(i+L-1))head++;
            if(key[q[head]]-key[i-1]>0){
                ans1=i,ans2=q[head];
                return true;
            }
        }
        head=1,tail=0;
        for(int i=L+1;i<=R+1;i+=2){
            while(head<=tail&&key[q[tail]]<key[i])tail--;
            q[++tail]=i;
        }
        if(key[q[head]]-key[1]>0){
            ans1=2,ans2=q[head];
            return true;
        }
        for(int i=4;i<=n;i+=2){
            while(head<=tail&&key[q[tail]]<key[i+R-1])tail--;
            q[++tail]=i+R-1;
            while(head<=tail&&q[head]<(i+L-1))head++;
            if(key[q[head]]-key[i-1]>0){
                ans1=i,ans2=q[head];
                return true;
            }
        }
        return false;
    }
    inline ll GCD(ll x,ll y){
        return x==0?y:GCD(y%x,x);
    }
    int main(){
        scanf("%d%d%d",&n,&L,&R),L+=L&1,R-=R&1;
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        for(ld l=0,r=1e9,mid;l+eps<=r;mid=(l+r)/2.,check(mid)?l=mid:r=mid);
        if(ans1==0){printf("0");return 0;}
        ll s=0,b=ans2-ans1+1;
        for(int i=ans1;i<=ans2;++i)s+=a[i>n?i-n:i];
        ll gcd=GCD(s,b);s/=gcd,b/=gcd;
        if(b==1)printf("%lld",s);
        else printf("%lld/%lld",s,b);
        return 0;
    }
  • 相关阅读:
    FTP-实例(Md5验证)
    Socket-实例
    函数对象、函数嵌套、名称空间与作用域、装饰器
    Docker——手动创建镜像
    Docker——桥接网络配置
    Docker——网络和存储(数据卷)
    Docker-PS命令解析
    面试题44:扑克牌的顺子
    面试题42:翻转单词顺序VS左旋转字符串
    面试题41:和为s的两个数字VS和为s的连续正数序列
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7593095.html
Copyright © 2011-2022 走看看