对无序数组求中位数,是一个比较经典的问题了。
有很多种办法求。
这题是边添加边求中位数的。
所以每插入一个数就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;
  }
}