您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
对于操作3,4,5,6每行输出一个数,表示对应答案
平衡树
平衡树模板题
注意Treap的删除操作的写法!!!
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define N 100005 #define inf 1000000000 using namespace std; int n,rt,tot; int rnd[N],l[N],r[N],v[N],w[N],sz[N]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void lturn(int &k) { int tmp=r[k];r[k]=l[tmp];l[tmp]=k; sz[tmp]=sz[k];sz[k]=sz[l[k]]+sz[r[k]]+w[k]; k=tmp; } void rturn(int &k) { int tmp=l[k];l[k]=r[tmp];r[tmp]=k; sz[tmp]=sz[k];sz[k]=sz[l[k]]+sz[r[k]]+w[k]; k=tmp; } void insert(int &k,int x) { if (!k){k=++tot;v[k]=x;sz[k]=w[k]=1;l[k]=r[k]=0;rnd[k]=rand();return;} sz[k]++; if (v[k]==x) w[k]++; else if (v[k]>x){insert(l[k],x);if (rnd[l[k]]<rnd[k]) rturn(k);} else{insert(r[k],x);if (rnd[r[k]]<rnd[k]) lturn(k);} } void del(int &k,int x)//一定要记住这里面sz[k]--的位置!!! { if (v[k]==x) { if (w[k]>1) w[k]--,sz[k]--; else if (!l[k]||!r[k]) k=l[k]+r[k]; else if (rnd[l[k]]<rnd[r[k]]) rturn(k),del(k,x); else lturn(k),del(k,x); return; } sz[k]--; if (x<v[k]) del(l[k],x); else del(r[k],x); } int getrnk(int k,int x) { if (v[k]==x) return sz[l[k]]+1; else if (x<v[k]) return getrnk(l[k],x); else return getrnk(r[k],x)+sz[l[k]]+w[k]; } int getkth(int k,int x) { if (sz[l[k]]<x&&sz[l[k]]+w[k]>=x) return v[k]; else if (x<=sz[l[k]]) return getkth(l[k],x); else return getkth(r[k],x-sz[l[k]]-w[k]); } int pre(int k,int x) { if (!k) return -inf; if (x<=v[k]) return pre(l[k],x); else { int tmp=pre(r[k],x); return tmp==-inf?v[k]:tmp; } } int suc(int k,int x) { if (!k) return inf; if (x>=v[k]) return suc(r[k],x); else { int tmp=suc(l[k],x); return tmp==inf?v[k]:tmp; } } int main() { srand(233); n=read(); F(i,1,n) { int opt=read(),x=read(); if (opt==1) insert(rt,x); else if (opt==2) del(rt,x); else if (opt==3) printf("%d\n",getrnk(rt,x)); else if (opt==4) printf("%d\n",getkth(rt,x)); else if (opt==5) printf("%d\n",pre(rt,x)); else printf("%d\n",suc(rt,x)); } return 0; }