P3369 普通平衡树(Treap做法)
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 xx 数
- 删除 xx 数(若有多个相同的数,因只删除一个)
- 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
- 查询排名为 xx 的数
- 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
- 求 xx 的后继(后继定义为大于 xx,且最小的数)
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+100; const int inf=1e9; //treap树 //利用BST的性质做查询和修改 //利用随机和堆优先级来保持平衡 struct Treap_tree { int ch[2]; int v; int dat;//优先级 int size;//子树节点数 int cnt;//重复数 }t[maxn]; int tot; int root; int newNode (int v) { tot++; t[tot].v=v; t[tot].dat=rand();//随机优先级 t[tot].size=1; t[tot].cnt=1; return tot; } void pushup (int x) { t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt; } void build () { root=newNode(-inf); t[root].ch[1]=newNode(inf); pushup(root); } void rotate (int &id,int d) { int tt=t[id].ch[d^1]; t[id].ch[d^1]=t[tt].ch[d]; t[tt].ch[d]=id; id=tt; pushup(t[id].ch[d]); pushup(id); } void ins (int &id,int v) { if (!id) { id=newNode(v); return; } if (v==t[id].v) t[id].cnt++; else { ins(t[id].ch[v>t[id].v],v); if (t[id].dat<t[t[id].ch[v>t[id].v]].dat) rotate(id,v<t[id].v); } pushup(id); } void remove (int &id,int v) { if (!id) return; if (v==t[id].v) { if (t[id].cnt>1) { t[id].cnt--; pushup(id); return; } if (t[id].ch[0]||t[id].ch[1]) { if (!t[id].ch[1]||t[t[id].ch[0]].dat>t[t[id].ch[1]].dat) { rotate(id,1); remove(t[id].ch[1],v); } else { rotate(id,0); remove(t[id].ch[0],v); } pushup(id); } else id=0; return; } remove(t[id].ch[v>t[id].v],v); pushup(id); } int rk (int id,int v) { if (!id) return 0; if (v==t[id].v) return t[t[id].ch[0]].size+1; else if (v<t[id].v) return rk(t[id].ch[0],v); else return t[t[id].ch[0]].size+t[id].cnt+rk(t[id].ch[1],v); } int kth (int id,int k) { if (!id) return inf; if (k<=t[t[id].ch[0]].size) return kth(t[id].ch[0],k); else if (k<=t[t[id].ch[0]].size+t[id].cnt) return t[id].v; else return kth(t[id].ch[1],k-t[t[id].ch[0]].size-t[id].cnt); } int get_pre (int id,int v) { int pre; while (id) { if (t[id].v<v) pre=t[id].v,id=t[id].ch[1]; else id=t[id].ch[0]; } return pre; } int get_next (int id,int v) { int nxt; while (id) { if (t[id].v>v) nxt=t[id].v,id=t[id].ch[0]; else id=t[id].ch[1]; } return nxt; } int main () { build(); int n; scanf("%d",&n); for (int i=1;i<=n;i++) { int op,x; scanf("%d%d",&op,&x); if (op==1) ins(root,x); if (op==2) remove(root,x); if (op==3) printf("%d\n",rk(root,x)-1); if (op==4) printf("%d\n",kth(root,x+1)); if (op==5) printf("%d\n",get_pre(root,x)); if (op==6) printf("%d\n",get_next(root,x)); } }