51nod1711 平均数

Posted 雨婷墨染

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1711 平均数相关的知识,希望对你有一定的参考价值。

Description

LYK有一个长度为n的序列a。
他最近在研究平均数。
他甚至想知道所有区间的平均数,但是区间数目实在太多了。
为了方便起见,你只要告诉他所有区间(n*(n+1)/2个区间)中第k大的平均数就行了。

Input

第一行两个数n,k(1<=n<=100000,1<=k<=n*(n+1)/2)。接下来一行n个数表示LYK的区间(1<=ai<=100000)。

Output

一行表示第k大的平均数,误差不超过1e-4就算正确。

Input示例

5 31 2 3 4 5

Output示例

4.000

思路

首先看题目求区间第k大,首先想到分第k大的平均数x。问题转化为如何快速求任意区间的平均数大于x的个数,先求求前缀和,则可以表示为(sum[r] - sum[l-1])/(r - l +1) > x 的区间个数,转化一下即为sum[r] - r*x > sum[l-1] - (l-1) * x;即形成一个新的数组sum[i]- i * x,求满足条件的区间有多少个,离散化一下,用树状数组统计一下就行。
注意:i从0开始,sum[0] = 0;也要算进去,不然会把0-1的区间漏掉。

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define MAXN 100010
 5 typedef long long ll;
 6 using namespace std;
 7 ll sum[MAXN];
 8 double a[MAXN],b[MAXN];
 9 int tree[MAXN];
10 int n;
11 ll k;
12 
13 int lowbit( int x)
14 {
15     return x & -x;
16 }
17 void add(int k)
18 {
19     while(k <= n + 1)
20     {
21         tree[k] ++;
22         k += lowbit(k);
23     }
24 }
25 int Sum(int k)
26 {
27     int sum = 0;
28     while(k)
29     {
30         sum += tree[k];
31         k -= lowbit(k);
32     }
33     return sum;
34 }
35 long long check(double x)
36 {
37     memset(tree, 0, sizeof(tree));
38     for(int i = 0; i <= n; i++)
39         a[i] = b[i] = sum[i] - i * x;
40     sort(a, a + 1 + n);
41     int num = unique(a, a + 1 + n) - a;
42     long long ans = 0;
43     for(int i = 0; i <= n; i++)
44     {
45         int temp = lower_bound(a, a + num, b[i]) - a + 1;
46         ans += Sum(temp);
47         add(temp);
48     }
49     return ans;
50 }
51 int main()
52 {
53     scanf("%d%I64d",&n,&k);
54     int temp;
55     sum[0] = 0;
56     for(int i =  1; i <= n; i++)
57     {
58         scanf("%d",&temp);
59         sum[i] = sum[i - 1] + temp;
60     }
61     double l = 1.0, r = 100000.0;
62     while(r - l >= 1e-6)
63     {
64         double mid = (l + r) / 2.0;
65         if (check(mid) >= k)
66             l = mid;
67         else
68             r = mid;
69     }
70     printf("%.4f\n",(r + l)/2.0);
71     return 0;
72 }

 

以上是关于51nod1711 平均数的主要内容,如果未能解决你的问题,请参考以下文章

51nod 平均数(马拉松14)

51nod 1227 平均最小公倍数

51nod1227 平均最小公倍数

51nod1227 平均最小公倍数

51Nod - 1098 最小方差

51nod_1098_最小方差