洛谷 P1168 中位数

给一个序列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;
} 

代码丑见谅qwq

原文地址:https://www.cnblogs.com/sdlang/p/13068051.html