对无序数组求中位数,是一个比较经典的问题了。
有很多种办法求。
这题是边添加边求中位数的。
所以每插入一个数就sort一遍复杂度太高显然不行。
还有一种利用大根堆小根堆,即平衡树来求,这种可以,这里不说。说另一种复杂度相当的,当常数教小的。
利用树状数组来求第K小。
建一个权值树状数组。例如有3,4,5,5,6四个数,那么
即树状数组中存的是某个区间的权值出现的次数。
由于这是一个32位无符号整型,范围过大必然使内存爆炸,所以需要离散化一下,先给原先的数组排一下序,就可以记录每个是是排在第几位,用这个排位来代替原值求,然后最后再转换回去。
所以就可以边插入边求得第,显然前个数的中位数就更新到第个数时的第大了,因为我们只要是奇数的。
那么显然第大的数,比如为则必然是,表示区间和
详见代码注释:
#include<bits/stdc++.h> #define endl '\n' #define rep(i,l,r) for(int i=l;i<=r;i++) #define per(i,r,l) for(int i=r;i>=l;i--) const int MX=20000+5; using namespace std; int cnt[MX]; int upd(int pos,int x)//更新权值树状数组 { // a[pos]++; for(;pos<MX;pos+=pos&-pos) { cnt[pos]+=x; } } int find_vk(int k)//求第k个权值 { int ans = 0,res = 0; for(int i=13;i>=0;i--)//i=log(mx); { ans+=(1<<i); if(ans>= MX||res+cnt[ans]>= k)ans-=(1<<i); else res+=cnt[ans]; } return ans+1; } struct node { int x,id; bool operator<(const node&that)const { return x<that.x; } }p[MX]; int a[MX],c[MX]; int main() { ios::sync_with_stdio(0),cin.tie(0); int n; int t; cin>>t; while(t--) { memset(cnt,0,sizeof cnt); int ca; cin>>ca>>n; rep(i,1,n) { int x; cin>>x; p[i].x=x; p[i].id=i; } cout<<ca<<" "<<n/2+1<<endl; int m=0; sort(p+1,p+n+1); rep(i,1,n)a[p[i].id]=i,c[i]=p[i].x;//对原数组离散化 rep(i,1,n) { upd(a[i],1); if(i&1) { int k=(i+1)/2; k=find_vk(k); cout<<c[k]<<" "; m++; if(m%10==0)cout<<endl; } } if(m%10)cout<<endl; } }