普通平衡树
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
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每行输出一个数,表示对应答案
样例输入
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
样例输出
106465
84185
492737
提示
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
存个Treap的板子qwq
#include<bits/stdc++.h> #define inf 0x7fffffff using namespace std; const int N=1e5+10; struct Treap{ int l,r; int val,dat; int cnt,si;}a[N]; int tot,root,n; void Update(int p) { a[p].si=a[a[p].l].si+a[a[p].r].si+a[p].cnt; } int New(int val) { a[++tot].val=val; a[tot].dat=rand(); a[tot].cnt=a[tot].si=1; return tot; } void build() { New(-inf); New(inf); root=1; a[1].r=2; Update(root); } void zig(int &p) { int q=a[p].l; a[p].l=a[q].r; a[q].r=p; p=q; Update(a[p].r); Update(p); } void zag(int &p) { int q=a[p].r; a[p].r=a[q].l; a[q].l=p; p=q; Update(a[p].l); Update(p); } void Insert(int &p,int val) { if (p==0) { p=New(val); return ; } if (val==a[p].val) { a[p].cnt++; Update(p); return; } if (val<a[p].val) { Insert(a[p].l,val); if (a[p].dat<a[a[p].l].dat) zig(p); } else { Insert(a[p].r,val); if (a[p].dat<a[a[p].r].dat) zag(p); } Update(p); } void Remove(int &p,int val) { if (p==0) return ; if (val==a[p].val) { if (a[p].cnt>1) {a[p].cnt--; Update(p); return ;} if (a[p].l||a[p].r) { if (a[p].r==0 || a[a[p].l].dat>a[a[p].r].dat) {zig(p); Remove(a[p].r,val);} else {zag(p); Remove(a[p].l,val);} Update(p); } else p=0; return ; } val < a[p].val ? Remove(a[p].l,val) : Remove(a[p].r,val); Update(p); } int GetRank(int p,int val) { if (p==0) return 0; if (val==a[p].val) return a[a[p].l].si+1; if (val<a[p].val) return GetRank(a[p].l,val); return GetRank(a[p].r,val)+a[a[p].l].si+a[p].cnt; } int GetVal(int p,int Rank) { if (p==0) return inf; if (a[a[p].l].si>=Rank) return GetVal(a[p].l,Rank); if (a[a[p].l].si+a[p].cnt>=Rank) return a[p].val; return GetVal(a[p].r,Rank-a[a[p].l].si-a[p].cnt); } int GetPre(int val) { int ans=1; int p=root; while (p) { if (val==a[p].val) { if (a[p].l>0) { p=a[p].l; while (a[p].r>0) p=a[p].r; ans=p; } break; } if (a[p].val<val && a[p].val>a[ans].val) ans=p; p=val < a[p].val ? a[p].l : a[p].r; } return a[ans].val; } int GetNext(int val) { int ans=2; int p=root; while (p) { if (val==a[p].val) { if (a[p].r>0) { p=a[p].r; while (a[p].l>0) p=a[p].l; ans=p; } break; } if (a[p].val>val && a[p].val<a[ans].val) ans=p; p=val < a[p].val ? a[p].l : a[p].r; } return a[ans].val; } int main() { build(); scanf("%d",&n); int op,x; while (n--) { scanf("%d%d",&op,&x); if (op==1) Insert(root,x); else if (op==2) Remove(root,x); else if (op==3) printf("%d\n",GetRank(root,x)-1); else if (op==4) printf("%d\n",GetVal(root,x+1)); else if (op==5) printf("%d\n",GetPre(x)); else printf("%d\n",GetNext(x)); } return 0; }