P3369 【模板】普通平衡树 —— Treap FHQtreap
【模板】普通平衡树
题目描述
您需要动态地维护一个可重集合 \(M\),并且提供以下操作:
- 向 \(M\) 中插入一个数 \(x\)。
- 从 \(M\) 中删除一个数 \(x\)(若有多个相同的数,应只删除一个)。
- 查询 \(M\) 中有多少个数比 \(x\) 小,并且将得到的答案加一。
- 查询如果将 \(M\) 从小到大排列后,排名位于第 \(x\) 位的数。
- 查询 \(M\) 中 \(x\) 的前驱(前驱定义为小于 \(x\),且最大的数)。
- 查询 \(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;
}
本文来自博客园,作者:Glowingfire,转载请注明原文链接:https://www.cnblogs.com/Glowingfire/p/18576060