[BZOJ 2017.11月 月赛] 组题

题目传送-BZOJ5090

题意:

给出n个数。求连续区间(长度大于等于k)最大平均值。
\(n \le 100000\)

题解:

二分答案,用double
O(n)check:先把原数组都减去二分的答案,判断有没有一段长度大于等于K的区间的元素和大于等于0就行了

过程:

由于BZOJ评测机过慢。。二分最大二分次数T了不知道多少发。。

代码:

inline db sgn(db x) {return x<-eps ? -1 : x>eps;}
const int N=100010;
int a[N];
db b[N];
int n,k;
int l,r;
inline bool judge(db x) {
    for(int i=1;i<=n;i++) b[i]=1.0*a[i]-x;
    db sum=0,pre=0,mi=0; l=1; r=k;
    for(int i=1;i<=k;i++) sum+=b[i]; if(sgn(sum)>=0) return true;
    for(int i=k+1;i<=n;i++) {
        sum+=b[i]; sum-=b[i-k];
    // if(x==1.25) printf("%lf\n",sum);
        pre+=b[i-k];
        if(pre<mi) {mi=pre; l=i-k+1;}
        if(sum+pre-mi>=0) {r=i; return true;}
    }
    return false;
}
signed main()
{
    read(n); read(k);
    for(int i=1;i<=n;i++) read(a[i]);
    db L=-1e8,R=1e8;
    db ret=0;
    int T=100;
    while(T--) {
        // printf("%lf %lf\n",L,R);
        db mid=(L+R)*0.5;
        if(judge(mid)) {ret=mid; L=mid;}
        else R=mid;
    }
    // assert(judge(1.25));
    assert(judge(ret));
    ll fz=0,fm=0;
    for(int i=l;i<=r;i++) fz+=a[i];
    fm=r-l+1;
    bool fl=0;
    if(fz<0) fl=1,fz=-fz;
    ll g=__gcd(fz,fm);
    // printf("%lld %lld %d %d\n",fz,fm,l,r);
    if(fl) putchar('-');
    printf("%lld/%lld\n",fz/g,fm/g);
    
    return 0;
}

用时:1h

转载于:https://www.cnblogs.com/functionendless/p/9442300.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值