51nod-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 3
1 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 100005
using 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值