给一个序列a,求前1,3,5......数的中位数
用(S[])来存(Ai)这个数出现了几次,但是(Ai<=10^9),如果直接建好树,那就直接爆掉了。所以我们动态开点,就要每次插入一个路径,如果路径上的数没出现过,那么就要插入这个点。当读进去一个数(X),看有没有到叶子节点,如果到了,那么(S[k]++),再更新节点,如果没到,那么就开一个新的点来存(X)出现的次数,所以我们需要两个数组(lc[])和(rc[])来存左右儿子。访问时也很简单,只要进行递归就行了,不过要注意,如果左儿子个数比要访问的(X)数小,也就是当(X>S[lc[k]])时,我们要访问右儿子,这时候是一个新的区间,所以(X)要变成(X-S[lc[k]])。
完整代码
#include <iostream>
using namespace std;
const int N=1e9;
int n,s[5000000],lc[5000000],rc[5000000],nc;
int insert(int &k,int l,int r,int v)
{
if (!k)nc++,k=nc;
if (l==r)
{
s[k]++;
return 0;
}
int mid=l+r>>1;
if (v<=mid)insert(lc[k],l,mid,v);
else insert(rc[k],mid+1,r,v);
s[k]=s[lc[k]]+s[rc[k]];
}
int query(int k,int l,int r,int x)
{
if (l==r)return l;
int mid=l+r>>1;
if (x<=s[lc[k]])return query(lc[k],l,mid,x);
else return query(rc[k],mid+1,r,x-s[lc[k]]);
}
int main()
{
int x,rt=0;
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>x;
insert(rt,1,N,x);
if (i%2==1)
cout<<query(1,1,N,(i+1)/2)<<endl;
}
return 0;
}