【题解】Luogu P3871 [TJOI2010]中位数

平衡树板题

原题传送门

这道题要用Splay,我博客里有对Splay的详细介绍

每次加入一个数,把数插入平衡树中

并且要记录一共有多少个数

每次查询就查询平衡树中第(总数-1)/2+1个数

十分暴力

#include <bits/stdc++.h>
#define N 110005
#define root tree[0].ch[1]
using namespace std;
inline int read()
{
	register int x=0,f=1;register char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x*f;
}
inline void write(register int x)
{
	if(!x)putchar('0');if(x<0)x=-x,putchar('-');
	static int sta[36];int tot=0;
	while(x)sta[tot++]=x%10,x/=10;
	while(tot)putchar(sta[--tot]+48);	
}
struct splay{
	int v,fa,ch[2],rec,sum;
}tree[N];
int tot=0;
inline bool findd(register int x)
{
	return x==tree[tree[x].fa].ch[0]?0:1;
}
inline void connect(register int x,register int fa,register int son)
{
	tree[x].fa=fa;
	tree[fa].ch[son]=x;
}
inline void update(register int x)
{
	tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].rec;
}
inline void rotate(register int x)
{
	int Y=tree[x].fa;
	int R=tree[Y].fa;
	int Yson=findd(x);
	int Rson=findd(Y);
	int B=tree[x].ch[Yson^1];
	connect(B,Y,Yson);
	connect(Y,x,Yson^1);
	connect(x,R,Rson);
	update(Y),update(x);
}
inline void splay(register int x,register int to)
{
	to=tree[to].fa;
	while(tree[x].fa!=to)
	{
		int y=tree[x].fa;
		if(tree[y].fa==to)
			rotate(x);
		else if(findd(x)==findd(y))
			rotate(y),rotate(x);
		else
			rotate(x),rotate(x);
	}
}
inline int newpoint(register int v,register int fa)
{
    tree[++tot].v=v;
    tree[tot].fa=fa;
    tree[tot].sum=tree[tot].rec=1;
    return tot;
}
inline void Insert(register int x)
{
	int now=root;
    if(root==0)
    {
        newpoint(x,0);
        root=tot;
    }
    else
    {
        while(19260817)
        {
            ++tree[now].sum;
            if(x==tree[now].v)
            {
                ++tree[now].rec;
                splay(now,root);
                return;
            }
            int nxt=x<tree[now].v?0:1;
            if(!tree[now].ch[nxt])
            {
                int p=newpoint(x,now);
                tree[now].ch[nxt]=p;
                splay(p,root);
                return;
            }
            now=tree[now].ch[nxt];
        }
    }
}
inline int arank(register int x)
{
    int now=root;
    while(19260817)
    {
        int used=tree[now].sum-tree[tree[now].ch[1]].sum;
        if(x>tree[tree[now].ch[0]].sum&&x<=used)
        {
            splay(now,root);
            return tree[now].v;
        }
        if(x<used)
            now=tree[now].ch[0];
        else
            x-=used,now=tree[now].ch[1];
    }
}
int main()
{
	int n=read();
	int sum=0;
	for(register int i=1;i<=n;++i)
	{
		int x=read();
		Insert(x);
		++sum;
	}
	int m=read();
	while(m--)
	{
		char ch=getchar();
		while(ch!='a'&&ch!='m')
			ch=getchar();
		if(ch=='a')
		{
			int x=read();
			Insert(x);
			++sum;
		}
		else if(ch=='m')
		{
			write(arank((sum-1)/2+1));
			printf("\n");
		}
	}
	return 0;
 } 
posted @ 2018-11-17 15:29  JSOI爆零珂学家yzhang  阅读(198)  评论(0编辑  收藏  举报