聯賽模擬測試5 平均數 二分答案+逆序對
阿新 • • 發佈:2020-09-23
## 題目描述
![](https://img2020.cnblogs.com/blog/1996139/202009/1996139-20200923202440344-583066088.png)
## 分析
之前做過類似的兩道題,一道是區間和的$k$小值,一道是眾數的$k$小值
那兩道統計的東西都有單調性,可以用兩個指標維護,$O(n)$計算
但是平均數沒有單調性,不能用兩個指標去掃
但是這道題的資料範圍是 $10^5$,時間限制是$2.5s$
統計答案時還可以再套一個$log$
如果當前列舉的平均值是$mid$的話
我們只需要找出所有$\frac{sum[j]-sum[i]}{j-i} \leq mid$的數對即可
我們把分母乘過去,就變成了$sum[i]-mid \times i \geq sum[j]-mid \times j$
可以看成區間求逆序對
用樹狀陣列做需要離散化,用歸併排序比較方便
## 程式碼
``` cpp
#include
#include
#include
typedef double db;
const int maxn=1e6+5;
const db eps=1e-6;
int n,a[maxn];
long long sum[maxn],m,js;
db b[maxn],c[maxn];
void msort(int l,int r){
if(l==r) return;
int mids=(l+r)>>1;
msort(l,mids);
msort(mids+1,r);
int now=l,t=l-1;
for(int i=mids+1;i<=r;i++){
while(b[now]=m) return 1;
else return 0;
}
int main(){
freopen("ave.in","r",stdin);
freopen("ave.out","w",stdout);
scanf("%d%lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i];
}
double l=-1e9,r=1e9,mids;
while(r-l>eps){
mids=(l+r)/2.0;
if(jud(mids)) r=mids;
else l=mids;
}
printf("%.4f\n",mids);
return 0;