51NOD 1711平均数

本文介绍了一种使用二分法解决特定区间平均数问题的方法,并提供了详细的数学推导过程及C++实现代码。

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

题目大意

有一个长度为n的序列a,求所有区间的平均数中第k大。

看题第一眼

什么鬼啊?!!

二分

可以想一下二分答案ans,就是要求平均数大于ans的区间个数有多少

求平均数大于ans的区间个数

首先转化成数学式子: sumisumjijans
那么式子可以再转化为:
sumisumjans×(ij)
sumisumjans×ians×j
sumians×isumjans×j
那么两边都分别只与i和j有关,于是我们可以将所有的 sumians×i 离散化,然后用个树状数组统计一下就好了

我打题时一开始没有把0也插入进去就错了啊,然后二分范围也要适当大一点,还有eps。

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1711

贴代码:

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>

#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)

using namespace std;

typedef long long LL;
typedef double db;

const int N = 100010;
const db eps = 1e-5;

LL a[N],k;
int num[N],level[N];
db v[N];
int n;
db l,r,mid,ans;
int tree[N];

bool cmp(int x,int y){
    return v[x]<v[y];
}

int get_t(int x){
    int tot=0;
    while(x){
        tot+=tree[x];
        x-=x&-x;
    }
    return tot;
}

void add(int x){
    while(x<=n){
        tree[x]++;
        x+=x&-x;
    }
}

LL gettot(db x){
    fo(i,1,n)v[i]=db(a[i])-x*i;
    sort(num,num+1+n,cmp);
    int u=0;
    fo(i,0,n){
        if (i==0||v[num[i]]-v[num[i-1]]>eps)u++;
        level[num[i]]=u;
    }
    fo(i,1,n)tree[i]=0;
    LL tot=0;
    add(level[0]);
    fo(i,1,n){
        tot+=get_t(level[i]);
        add(level[i]);
    }
    return tot;
}

int main(){
    freopen("average.in","r",stdin);
    freopen("average.out","w",stdout);
    scanf("%d%lld",&n,&k);
    fo(i,1,n)scanf("%lld",&a[i]);
    fo(i,1,n){
        a[i]+=a[i-1];
        num[i]=i;
    }
    l=0,r=100001,ans=0;
    while(l+eps<=r){
        mid=(l+r)/2;
        if (gettot(mid)>=k)l=mid+eps;
        else{
            r=mid-eps;
            ans=mid;
        }
    }
    printf("%.4lf\n",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值