51nod-1711 平均数

来源:互联网 发布:诺诗兰官方旗舰店淘宝 编辑:程序博客网 时间:2024/06/06 02:49

原题链接

1711 平均数
基准时间限制:4 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
 收藏
 关注
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

二分枚举平均数求出大于等于它的区间个数

(sum[i] - sum[j]) / (i - j) >= avg  --->  sum[i] - i * avg >= sum[j] - j * avg,用该式子加上树状数组求出大于等于某平均数的区间个数

#include <bits/stdc++.h>#define MOD 1000000007#define maxn 100005using namespace std;typedef long long ll;struct Node{double p;int k1, k2;}node[maxn];ll num[maxn];ll n, k, sum[maxn];void Update(int j){while(j <= n+1){sum[j]++;j += j & -j;}}int Query(int j){int e = 0;while(j){e += sum[j];j -= j & -j;}return e;}bool cmp1(const Node&a, const Node&b){return a.p < b.p;}bool cmp2(const Node&a, const Node&b){return a.k1 < b.k1;}bool judge(double m){ll ans = 0;for(int i = 1; i <= n+1; i++){node[i].p = num[i] - m * i;node[i].k1 = i;}sort(node+1, node+2+n, cmp1);for(int i = 1; i <= n+1; i++)  node[i].k2 = i;sort(node+1, node+2+n, cmp2);memset(sum, 0, sizeof(sum));for(int i = 1; i <= n+1; i++){ans += Query(node[i].k2);Update(node[i].k2);} if(ans >= k) return true;return false;}int main(){//freopen("in.txt", "r", stdin);scanf("%I64d%I64d", &n, &k);for(int i = 2; i <= n+1; i++){ scanf("%I64d", num+i); num[i] += num[i-1];   }double l = 0, r = 100000;while(r - l > 1e-5){double mid = (l + r) / 2;if(judge(mid)) l = mid;else r = mid;}printf("%.5lf\n", l);return 0;}


0 0