模板:有旋treap
有旋转的treap,其实rotate比较难理解
没关系,上板子:
题目还是普通平衡树
#include<iostream> #include<cstdio> #include<algorithm> #define MAXN 100005 using namespace std; int n,opt,x,root=0,np; struct node{ int ch[MAXN][2],val[MAXN],size[MAXN],cnt[MAXN],prior[MAXN]; void update(int now){ size[now]=size[ch[now][0]]+size[ch[now][1]]+cnt[now]; } void rotate(int &now,int dir){ int son=ch[now][dir^1]; ch[now][dir^1]=ch[son][dir]; ch[son][dir]=now; update(now); update(now=son); } void insert(int &now,int x){ if(!now){ now=++np; size[now]=cnt[now]=1; prior[now]=rand(); val[now]=x; return ; } size[now]++; if(val[now]==x){ cnt[now]++; return ; } int d=x>val[now]; insert(ch[now][d],x); if(prior[ch[now][d]]<prior[now]) rotate(now,d^1); } void remove(int &now,int num){ if(!now) return; if(val[now]==num){ if(cnt[now]>1){ size[now]--; cnt[now]--; return; } if(!ch[now][0]||!ch[now][1]){ now=ch[now][0]+ch[now][1]; return; } int d=prior[ch[now][1]]<prior[ch[now][0]]; rotate(now,d^1); remove(now,num); return; } size[now]--; int d=num>val[now]; remove(ch[now][d],num); } int get_rank(int now, int num){ if(!now) return 0; if(num==val[now]) return size[ch[now][0]]+1; int d=num>val[now]; if(d) return size[ch[now][0]]+cnt[now]+get_rank(ch[now][1],num); return get_rank(ch[now][0],num); } int get_k(int now,int k){ while(now){ if(k<=size[ch[now][0]]) now=ch[now][0]; else if(k>size[ch[now][0]]+cnt[now]) k-=size[ch[now][0]]+cnt[now],now=ch[now][1]; else return val[now]; } } int get_pre(int now,int num){ if(!now) return -0x7fffffff; if(num<=val[now]) return get_pre(ch[now][0],num); return max(val[now],get_pre(ch[now][1],num)); } int get_next(int now,int num){ if(!now) return 0x7fffffff; if(num>=val[now]) return get_next(ch[now][1],num); return min(val[now],get_next(ch[now][0],num)); } }treap; int main(){ scanf("%d",&n); while(n--){ scanf("%d%d",&opt,&x); if(opt==1) treap.insert(root,x); else if(opt==2) treap.remove(root, x); else if(opt==3) printf("%d\n",treap.get_rank(root,x)); else if(opt==4) printf("%d\n",treap.get_k(root,x)); else if(opt==5) printf("%d\n",treap.get_pre(root,x)); else if(opt==6) printf("%d\n",treap.get_next(root,x)); } return 0; }