3316: JC loves Mkk 二分答案+单调队列

本文介绍了一种使用二分查找结合单调队列解决平均数最大化问题的方法。通过二分答案并利用单调队列维护前缀和,实现对特定区间内元素的快速查找与比较。适用于需要求解区间最小值的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

…平均数最大我居然不知道要二分答案,似乎是很常见的思路?我好弱。

每次二分一个答案mid,维护aimid的前缀和,每次枚举一个i,将sumiL加入单调队列,并保证队列中的点都在iR..iL之内,每次要找区间的最小值mn,看看sumimn0是否成立,维护最小值可以单调队列来解决。

#include<iostream>
#include<cstdio>
#define eps 1e-7
#define N 200005
using namespace std;
long double sum[N];
int a[N];
int n,L,R,mx;
int Q[2][N],l[2],r[2];
long long ans;
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
bool judge(long double y)
{
    for (int i=1;i<=n;i++)
        sum[i]=sum[i-1]+a[i]-y;
    l[0]=l[1]=1; 
    r[0]=r[1]=0;
    for (int i=L;i<=n;i++)
    {
        int w=i&1,x=i-L;
        int *q=Q[w];
        while (r[w]>=l[w]&&sum[x]<sum[q[r[w]]]) r[w]--;
        while (r[w]>=l[w]&&q[l[w]]<i-R) l[w]++;
        q[++r[w]]=x;
        if (sum[i]-sum[q[l[w]]]>=0) return ans=i-q[l[w]];
    }
    return false;
}
int main()
{
    n=read(); L=read(); R=read();
    if (L&1) L++;
    if (R&1) R--;
    for (int i=1;i<=n;i++)
    {
        a[i]=read();
        mx=max(a[i],mx);
        a[i+n]=a[i];
    }
    n<<=1;
    long double l=0,r=mx;
    while (r-l>=eps)
    {
        long double mid=(l+r)/2;
        if (judge(mid)) l=mid;
        else r=mid;
    }
    long double x=(l+r)/2;
    long long w=(long long)(ans*x+0.5);
    long long d=gcd(w,ans);
    w/=d; ans/=d;
    if (ans==1) cout << w;
    else cout << w << "/" << ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值