【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;
}

 

posted @ 2017-09-25 17:56  TS_Hugh  阅读(246)  评论(1编辑  收藏  举报