Luogu P3871中位数 (splay求中位数)

在这里插入图片描述

AC Code

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct splay_tree
{
    int ff,cnt,ch[2],val,size;
}tr[N];
int root,tot;
void update(int x)
{
    tr[x].size=tr[tr[x].ch[0]].size+tr[tr[x].ch[1]].size+tr[x].cnt;
}
void rotate(int x)
{
    int y=tr[x].ff;
    int z=tr[y].ff;
    int k=(tr[y].ch[1]==x);
    tr[z].ch[(tr[z].ch[1]==y)]=x;
    tr[x].ff=z;
    tr[y].ch[k]=tr[x].ch[k^1];
    tr[tr[x].ch[k^1]].ff=y;
    tr[x].ch[k^1]=y;
    tr[y].ff=x;
    update(y);
    update(x);
}
void splay(int x,int s)
{
    while(tr[x].ff!=s)
    {
        int y=tr[x].ff,z=tr[y].ff;
        if(z!=s) 
            (tr[z].ch[0]==y)^(tr[y].ch[0]==x)?rotate(x):rotate(y);
        rotate(x);
    }
    if(s==0) root=x;
}
void find(int x)
{
    int u=root;
    if(!u) return ;
    while(tr[u].ch[x>tr[u].val]&&x!=tr[u].val)
        u=tr[u].ch[x>tr[u].val];
    splay(u,0);
}
void insert(int x)
{
    int u=root,ff=0;
    while(u&&tr[u].val!=x)
    {
        ff=u;
        u=tr[u].ch[x>tr[u].val];
    }
    if(u) tr[u].cnt++;
    else
    {
        u=++tot;
        if(ff) tr[ff].ch[x>tr[ff].val]=u;
        tr[u].ch[0]=tr[u].ch[1]=0;
        tr[tot].cnt=1;
        tr[tot].val=x;
        tr[tot].ff=ff;
        tr[tot].size=1;
    }
    splay(u,0);
}
int kth(int x)
{
    int u=root;
    while(tr[u].size<x) return 0;
    while(1)
    {
        int y=tr[u].ch[0];
        if(x>tr[y].size+tr[u].cnt)
        {
            x-=tr[y].size+tr[u].cnt;
            u=tr[u].ch[1];
        }
        else if(tr[y].size>=x)
            u=y;
        else return tr[u].val;
    }
}
int main()
{
    insert(-1e9+10);
    insert(1e9+10);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        insert(x);
    }
    n=n+2;
    int m;
    scanf("%d",&m);
    while(m--)
    {
        string str;
        cin>>str;
        if(str=="add")
        {
            int x;
            cin>>x;
            insert(x);
            n++;
        }
        else
        {
            int res=kth((n+1)/2);
            printf("%d\n",res);
        }
    }
    //system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值