51nod平均数

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long int64;
 8 const double eps=1e-5;
 9 const int maxn=100005;
10 int n,a[maxn],sum[maxn],pos[maxn];
11 double l,r,mid,ans,b[maxn],s[maxn],list[maxn];
12 int64 k;
13 int lowbit(int x){return x&(-x);}
14 void insert(int x){for (int i=x;i<=n+1;i+=lowbit(i)) sum[i]++;}
15 int64 query(int x){
16     int64 temp=0;
17     for (int i=x;i;i-=lowbit(i)) temp+=sum[i];
18     return temp; 
19 }
20 bool judge(double num){
21     memset(sum,0,sizeof(sum)); b[0]=0;
22     for (int i=1;i<=n;i++) b[i]=a[i]-num;
23     for (int i=1;i<=n;i++) s[i]=s[i-1]+b[i],list[i]=s[i];
24     list[n+1]=0; sort(list+1,list+n+2);
25     for (int i=1;i<=n;i++) pos[i]=lower_bound(list+1,list+n+2,s[i])-list;
26     pos[0]=lower_bound(list+1,list+n+2,0)-list;
27     int64 tot=0;
28     insert(pos[0]);
29     for (int i=1;i<=n;i++) tot+=query(pos[i]),insert(pos[i]);
30     return tot>=k;
31 }
32 int main(){
33     scanf("%d%lld",&n,&k);
34     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
35     l=1.0,r=100000.0;
36     while (l+eps<r){
37         mid=(l+r)/2.0;
38         if (judge(mid)) l=mid;
39         else r=mid;
40     }
41     printf("%.4lf\n",l);
42     return 0;
43 }
View Code

题目大意:

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

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