P3369 【模板】普通平衡树 —— Treap FHQtreap

【模板】普通平衡树

题目描述

您需要动态地维护一个可重集合 \(M\),并且提供以下操作:

  1. \(M\) 中插入一个数 \(x\)
  2. \(M\) 中删除一个数 \(x\)(若有多个相同的数,应只删除一个)。
  3. 查询 \(M\) 中有多少个数比 \(x\) 小,并且将得到的答案加一。
  4. 查询如果将 \(M\) 从小到大排列后,排名位于第 \(x\) 位的数。
  5. 查询 \(M\)\(x\) 的前驱(前驱定义为小于 \(x\),且最大的数)。
  6. 查询 \(M\)\(x\) 的后继(后继定义为大于 \(x\),且最小的数)。

对于操作 3,5,6,不保证当前可重集中存在数 \(x\)

输入格式

第一行为 \(n\),表示操作的个数,下面 \(n\) 行每行有两个数 \(\text{opt}\)\(x\)\(\text{opt}\) 表示操作的序号($ 1 \leq \text{opt} \leq 6 $)

输出格式

对于操作 \(3,4,5,6\) 每行输出一个数,表示对应答案。

样例 #1

样例输入 #1

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

样例输出 #1

106465
84185
492737

提示

【数据范围】
对于 \(100\%\) 的数据,\(1\le n \le 10^5\)\(|x| \le 10^7\)

来源:Tyvj1728 原名:普通平衡树

在此鸣谢

分析

模板

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100,M=1e6+100;
struct node
{
    int lc,rc,pre,val,siz;
}t[N];
int tot,root,n;
void create(int x)
{
    ++tot;
    t[tot].lc=t[tot].rc=0;
    t[tot].val=x;
    t[tot].siz=1;
    t[tot].pre=rand();
}
void upd(int x)
{
    t[x].siz=t[t[x].lc].siz+t[t[x].rc].siz+1;
}
void split(int u,int x,int &L,int &R)
{
    if(u==0){L=R=0;return ;}
    if(t[u].val<=x)
    {
        L=u;
        split(t[u].rc,x,t[u].rc,R);
    }
    else
    {
        R=u;
        split(t[u].lc,x,L,t[u].lc);
    }
    upd(u);
}
int merg(int L,int R)
{
    if(L==0 || R==0)return L+R;
    if(t[L].pre>t[R].pre)
    {
        t[L].rc=merg(t[L].rc,R);
        upd(L);
        return L;
    }
    else
    {
        t[R].lc=merg(L,t[R].lc);
        upd(R);
        return R;
    }
}
void inser(int x)
{
    int L=0,R=0;
    create(x);
    split(root,x,L,R);
    L=merg(L,tot);
    root=merg(L,R);
}
void del(int x)
{
    int L=0,R=0,nw=0;
    split(root,x,L,R);
    split(L,x-1,L,nw);
    nw=merg(t[nw].lc,t[nw].rc);
    L=merg(L,nw);
    root=merg(L,R);
}
int finx(int x)
{
    int L=0,R=0,nw=0;
    split(root,x-1,L,R);
    nw=t[L].siz+1;
    root=merg(L,R);
    return nw;
}
int rk(int u,int k)
{
    if(t[t[u].lc].siz+1==k)return u;
    if(t[t[u].lc].siz>=k)return rk(t[u].lc,k);
    else return rk(t[u].rc,k-t[t[u].lc].siz-1);
}
int pre_x(int x)
{
    int L=0,R=0,nw=0;
    split(root,x-1,L,R);///L==0 -->RE
    nw=t[ rk(L,t[L].siz) ] .val;
    root=merg(L,R);
    return nw;
}

int suf_x(int x)
{
    int L=0,R=0,nw=0;
    split(root,x,L,R);
    nw=t[ rk(R,1) ] .val;
    root=merg(L,R);
    return nw;
}

void work()
{
    cin>>n;
    int opt,x;
    while(n--)
    {
        scanf("%d%d",&opt,&x);
        if(opt==1)inser(x);
        else if(opt==2)del(x);
        else
        {
            int ans=0;
            if(opt==3)ans=finx(x);
            else if(opt==4)ans=t[rk(root,x)].val;
            else if(opt==5)ans=pre_x(x);
            else ans=suf_x(x);
            printf("%d\n",ans);
        }
    }
}

int main()
{
    work();
    return 0;
}














posted @ 2024-11-29 10:50  Glowingfire  阅读(1)  评论(0编辑  收藏  举报