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

【模板】普通平衡树

题目描述

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

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

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

输入格式

第一行为 n,表示操作的个数,下面 n 行每行有两个数 optxopt 表示操作的序号(1opt6

输出格式

对于操作 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% 的数据,1n105|x|107

来源: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 @   Glowingfire  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示