1. 程式人生 > >聯賽模擬測試5 平均數 二分答案+逆序對

聯賽模擬測試5 平均數 二分答案+逆序對

## 題目描述 ![](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;