51nod平均数

时间:2022-06-26 18:55:44
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long int64;
const double eps=1e-;
const int maxn=;
int n,a[maxn],sum[maxn],pos[maxn];
double l,r,mid,ans,b[maxn],s[maxn],list[maxn];
int64 k;
int lowbit(int x){return x&(-x);}
void insert(int x){for (int i=x;i<=n+;i+=lowbit(i)) sum[i]++;}
int64 query(int x){
int64 temp=;
for (int i=x;i;i-=lowbit(i)) temp+=sum[i];
return temp;
}
bool judge(double num){
memset(sum,,sizeof(sum)); b[]=;
for (int i=;i<=n;i++) b[i]=a[i]-num;
for (int i=;i<=n;i++) s[i]=s[i-]+b[i],list[i]=s[i];
list[n+]=; sort(list+,list+n+);
for (int i=;i<=n;i++) pos[i]=lower_bound(list+,list+n+,s[i])-list;
pos[]=lower_bound(list+,list+n+,)-list;
int64 tot=;
insert(pos[]);
for (int i=;i<=n;i++) tot+=query(pos[i]),insert(pos[i]);
return tot>=k;
}
int main(){
scanf("%d%lld",&n,&k);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
l=1.0,r=100000.0;
while (l+eps<r){
mid=(l+r)/2.0;
if (judge(mid)) l=mid;
else r=mid;
}
printf("%.4lf\n",l);
return ;
}

题目大意:

LYK有一个长度为n的序列a。

他最近在研究平均数。
他甚至想知道所有区间的平均数,但是区间数目实在太多了。
为了方便起见,你只要告诉他所有区间(n*(n+1)/2个区间)中第k大的平均数就行了。
做法:二分很容易理解,问题转化为有多少个区间的平均数>=x,对于平均数,我们把每个数减去x,若该区间的sum大于等于0,则说明该区间的平均数大于等于x,那么问题便进一步的转化为有多少个区间的和非负,这个可以在nlogn的时间内求出,求出前缀和并离散化后,用线段树或树状数组可以求出来,时间总复杂度为nlognlogR,可以过,这是我的运行情况:Accepted 1500 ms 5592 KB 。