bzoj3316: JC loves Mkk

来源:互联网 发布:楚天消防网通知通告 编辑:程序博客网 时间:2024/05/21 14:56

题意

给你一个环
让你找到连续的长度∈【l,r】的序列,哦,还要是偶数
并使他的平均数最大

题解

看到环和序列就肯定是copy一份啦
然后平均数最大,多半是二分。。
然后偶数和奇数。。不会了。。
网上说是对于奇数位和偶数位各开一个单调队列,新姿势Get
然后就完了。。
CODE:

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>using namespace std;const int N=100005*2;int n,L,R;int a[N];int mx;int q[2][N],l[2],r[2];//两个单调队列 long long ans;//选了多少个数 long double sum[N];bool check (long double x){    for (int u=1;u<=n;u++) sum[u]=sum[u-1]+a[u]-x;    l[1]=l[0]=1;r[1]=r[0]=0;    for (int u=L;u<=n;u++)    {        int w=u&1;        int x=u-L;        while (l[w]<=r[w]&&sum[x]<sum[q[w][r[w]]]) r[w]--;        while (l[w]<=r[w]&&q[w][l[w]]<u-R) l[w]++;        q[w][++r[w]]=x;        if (sum[u]-sum[q[w][l[w]]]>=0)        {            ans=(long long)(u-q[w][l[w]]);            return true;        }    }    return false;}long long gcd(long long x,long long y){return x==0?y:gcd(y%x,x);}int main(){    scanf("%d%d%d",&n,&L,&R);    for (int u=1;u<=n;u++)      {        scanf("%d",&a[u]);        mx=max(a[u],mx);    }    for (int u=1;u<=n;u++) a[u+n]=a[u];    n*=2;    if (L%2!=0) L++;if (R%2!=0) R--;    long double l=0,r=(long double)mx;    while (r-l>1e-7)    {        long double mid=(l+r)/2.0;        if (check(mid)) l=mid;        else r=mid;    }    long double x=(l+r)/2;       long long w=(long long)(ans*x+0.5);    long long ooo=gcd(w,ans);    ans/=ooo;w/=ooo;    if (ans==1) printf("%lld\n",w);    else printf("%lld/%lld\n",w,ans);    return 0;}