原题链接
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;
}