ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

Input

第1行,包含三个整数。n,L,R。
第2行n个数,代表a[1..n]。

Output


仅1行,表示询问答案。
如果答案是整数,就输出整数;否则,输出既约分数“P/Q”来表示。

随机数据不卡精度所以可以分数规划二分答案

用两个单调队列维护奇偶位置上的前缀和,可以判定是否存在在[L,R]内的正权值偶数长度子串

#include<cstdio>
typedef long long i64;
char buf[10000007],*ptr=buf-1;
int _(){
    int x=0,c=*++ptr;
    while(c<48)c=*++ptr;
    while(c>47)x=x*10+c-48,c=*++ptr;
    return x;
}
int n,l,r;
int a[200007];
double s[200007];
int s1[200007],s2[200007],l1,r1,l2,r2;
i64 gcd(i64 a,i64 b){
    for(i64 c;b;c=a,a=b,b=c%b);
    return a;
}
int main(){
    buf[fread(buf,1,sizeof(buf),stdin)]=0;
    n=_();l=_();r=_();
    if(l&1)++l;
    if(r&1)--r;
    double L=0,R=0;
    for(int i=1;i<=n;++i){
        a[i]=_();
        if(a[i]>R)R=a[i];
        a[n+i]=a[i];
    }
    int lp=0,rp=0;
    while(L<R){
        double M=(L+R)/2;
        int l0=0,r0=0;
        l1=l2=1;r1=r2=0;
        for(int i=1;i<=n*2;++i){
            s[i]=s[i-1]+a[i]-M;
            if(i-l>=0){
                if(i-l&1){
                    while(l1<=r1&&s[s1[r1]]>s[i-l])--r1;
                    s1[++r1]=i-l;
                }else{
                    while(l2<=r2&&s[s2[r2]]>s[i-l])--r2;
                    s2[++r2]=i-l;
                }
            }
            if(i&1){
                while(l1<=r1&&s1[l1]<i-r)++l1;
                if(l1<=r1&&s[s1[l1]]<s[i]){
                    l0=s1[l1]+1;
                    r0=i;
                    break;
                }
            }else{
                while(l2<=r2&&s2[l2]<i-r)++l2;
                if(l2<=r2&&s[s2[l2]]<s[i]){
                    l0=s2[l2]+1;
                    r0=i;
                    break;
                }
            }
        }
        if(l0){
            lp=l0;rp=r0;
            L=M+1e-8;
        }else R=M-1e-8;
    }
    i64 A=0,B=rp-lp+1,g;
    for(int i=lp;i<=rp;++i)A+=a[i];
    g=gcd(A,B);
    A/=g;B/=g;
    if(B==1)printf("%lld",A);
    else printf("%lld/%lld",A,B);
    return 0;
}

 

posted on 2016-12-27 21:39  nul  阅读(232)  评论(0编辑  收藏  举报