解题关键:无旋treap模板。
#include<iostream> #include<cstdio> #include<cstring> #include<ctime> #include<cstdlib> #include<cmath> #include<algorithm> #define maxn 500001 using namespace std; typedef long long ll; int size[maxn],ch[maxn][2],rnd[maxn],val[maxn]; int ncnt,n,x,y,z,rt; inline void pushup(int x){ size[x]=1+size[ch[x][0]]+size[ch[x][1]]; } inline int new_node(int x){ size[++ncnt]=1; val[ncnt]=x; rnd[ncnt]=rand(); return ncnt; } //核心 int merge(int A,int B){ if(!A||!B) return A+B; if(rnd[A]<rnd[B]){ch[A][1]=merge(ch[A][1],B); pushup(A);return A;} else {ch[B][0]=merge(A,ch[B][0]); pushup(B);return B;} } //权值分裂 void split(int now,int k,int &x,int &y){ if(!now) x=y=0; else{ if(val[now]<=k) x=now,split(ch[now][1],k,ch[now][1],y); else y=now,split(ch[now][0],k,x,ch[now][0]); pushup(now); } } //排名分裂 void split_2(int now,int k,int &x,int &y){ if(!now) x=y=0; else{ if(k<=size[ch[now][0]]){y=now;split(ch[now][0],k,x,ch[now][0]);} else{x=now;split(ch[now][1],k-size[ch[now][0]]-1,ch[now][1],y);} pushup(now); } } void insert(int &k,int a){ split(k,a,x,y); k=merge(merge(x,new_node(a)),y); } //会浪费空间,没有回收节点 void del(int &k,int a){ split(k,a,x,z); split(x,a-1,x,y); y=merge(ch[y][0],ch[y][1]); k=merge(merge(x,y),z); } int rnk(int &k,int a){ split(k,a-1,x,y); int res=size[x]+1; k=merge(x,y); return res; } int kth(int now,int k){ while(1){ if(k<=size[ch[now][0]]) now=ch[now][0]; else if(k==size[ch[now][0]]+1) return val[now]; else k-=size[ch[now][0]]+1,now=ch[now][1]; } } int pred(int &k,int a){ split(k,a-1,x,y); int res=kth(x,size[x]); k=merge(x,y); return res; } int succ(int &k,int a){ split(k,a,x,y); int res=kth(y,1); k=merge(x,y); return res; } int main(){ srand(time(0)); scanf("%d",&n); for(int i=1,opt,a;i<=n;i++){ scanf("%d%d",&opt,&a); switch(opt){ case 1:insert(rt,a);break; case 2:del(rt,a);break; case 3:printf("%d\n",rnk(rt,a));break; case 4:printf("%d\n",kth(rt,a));break; case 5:printf("%d\n",pred(rt,a));break; case 6:printf("%d\n",succ(rt,a));break; } } return 0; }
原文:https://www.cnblogs.com/elpsycongroo/p/10371406.html