[Luogu 1168] 中位数

Posted Capella

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu 1168] 中位数相关的知识,希望对你有一定的参考价值。

<题目链接>

中位数可以转化为区间第k大问题,因此想到Treap实现名次树。(笑)

插入第i个数,随即询问当前排名第(i+1>>1)的数。

代码走起。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
const int MAXN=100010;
int n;
class Treap
{
    public:
        Treap(void)
        {
            rt=cnt=0;
            memset(a,0,sizeof a);
            memset(s,0,sizeof s);
        }
        void Insert(int x)
        {
            _Insert(rt,x);
        }
        int Xth(int x)
        {
            return _Xth(rt,x);
        }
    private:
        bool a[MAXN];
        int rt,cnt,ans;
        struct node
        {
            int l,r,v,p,size,num;
        }s[MAXN];
        int Random(void)
        {
            int x;
            while(a[x=rand()%MAXN]);
            a[x]=1;
            return x;
        }
        void Update(int i)
        {
            s[i].size=s[s[i].l].size+s[s[i].r].size+s[i].num;
        }
        void L_Rotate(int &i)
        {
            int t=s[i].r;
            s[i].r=s[t].l,s[t].l=i;
            s[t].size=s[i].size;
            Update(i),i=t;
        }
        void R_Rotate(int &i)
        {
            int t=s[i].l;
            s[i].l=s[t].r,s[t].r=i;
            s[t].size=s[i].size;
            Update(i),i=t;
        }
        void _Insert(int &i,int x)
        {
            if(!i)
            {
                s[i=++cnt].v=x,s[i].p=Random();
                s[i].size=s[i].num=1;
                return;
            }
            ++s[i].size;
            if(x==s[i].v)
                ++s[i].num;
            else if(x<s[i].v)
            {
                _Insert(s[i].l,x);
                R_Rotate(i);
            }
            else
            {
                _Insert(s[i].r,x);
                L_Rotate(i);
            }
        }
        int _Xth(int i,int x)
        {
            if(!i)
                return 0;
            int t;
            if(x<=s[s[i].l].size)
                return _Xth(s[i].l,x);
            else if(x>(t=s[s[i].l].size+s[i].num))
                return _Xth(s[i].r,x-t);
            else
                return s[i].v;
        }
}T;
int main(int argc,char *argv[])
{
    scanf("%d",&n);
    srand((unsigned)time(NULL));
    for(int i=1,x;i<=n;++i)
    {
        scanf("%d",&x);
        T.Insert(x);
        if(i&1)
            printf("%d\n",T.Xth(i+1>>1));
    }
    return 0;
}

谢谢阅读。

以上是关于[Luogu 1168] 中位数的主要内容,如果未能解决你的问题,请参考以下文章

洛谷—— P1168 中位数

[洛谷P1168]中位数

P1168 中位数

中位数

P1168 中位数

洛谷P1168 中位数 堆