這是一道模板題,其數據比「普通平衡樹」更強。html
如未特別說明,如下全部數據均爲整數。ios
維護一個多重集 S SS ,初始爲空,有如下幾種操做:ui
操做共 n nn 次。spa
第一行一個整數 n nn,表示共有 n nn 次操做 。debug
接下來 n nn 行,每行爲如下幾種格式之一 :code
0 x
,把 x xx 加入 S SS1 x
,刪除 S SS 中的一個 x xx,保證刪除的數在 S SS 中必定存在2 k
,求 S SS 中第 k kk 小的數,保證要求的數在 S SS 中必定存在3 x
,求 S SS 中有多少個數小於 x xx4 x
,求 S SS 中小於 x xx 的最大數,若是不存在,輸出 −1 -1−15 x
,求 S SS 中大於 x xx 的最小數,若是不存在,輸出 −1 -1−1對於每次詢問,輸出單獨一行表示答案。htm
5 0 3 0 4 2 2 1 4 3 3
4 0
1≤n≤3×105,0≤x≤109 1 \leq n \leq 3 \times 10 ^ 5, 0 \leq x \leq 10 ^ 91≤n≤3×105,0≤x≤109blog
#include<iostream> #include<cstdio> #include<cstring> #define INF 0x7fffffff #define maxn 400010 using namespace std; int m,rt,son[maxn][2],fa[maxn],val[maxn],cnt[maxn],sz[maxn],size; void update(int x){ sz[x]=sz[son[x][1]]+sz[son[x][0]]+cnt[x]; } void rotate(int x,int &k){ int y=fa[x],z=fa[fa[x]],l,r; if(son[y][0]==x)l=0;else l=1;r=l^1; if(y==k)k=x; else son[z][son[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[son[x][r]]=y; son[y][l]=son[x][r];son[x][r]=y; update(y);update(x); } void splay(int x,int &k){ while(x!=k){ int y=fa[x],z=fa[fa[x]]; if(y!=k){ if((son[z][0]==y)^(son[y][0]==x))rotate(x,k); else rotate(y,k); } rotate(x,k); } } void Insert(int v){ int y=0,k=rt; while(k&&val[k]!=v)y=k,k=son[k][v>val[k]]; if(k)cnt[k]++; else { k=++size; cnt[k]=sz[k]=1; fa[k]=y;val[k]=v; if(y)son[y][v>val[y]]=k; } splay(k,rt); } int find2(int x){ x++;int k=rt; if(sz[k]<x)return 0; while(1){ if(sz[son[k][0]]<x&&sz[son[k][0]]+cnt[k]>=x)return k; if(sz[son[k][0]]>=x)k=son[k][0]; else x-=sz[son[k][0]]+cnt[k],k=son[k][1]; } return k; } void find1(int x){ int k=rt;if(!k)return; while(son[k][x>val[k]]&&val[k]!=x) k=son[k][x>val[k]]; splay(k,rt); } int nxt(int x,int f){ find1(x);//if(!rt)return 0; if((val[rt]>x&&f)||(val[rt]<x&&!f))return rt; int k=son[rt][f]; while(son[k][f^1])k=son[k][f^1]; return k; } void del(int v){ find1(v); int x=rt,k; if(cnt[rt]>1){cnt[rt]--;sz[rt]--;return;} if(son[rt][0]*son[rt][1]==0){ rt=son[rt][0]+son[rt][1]; } else { k=son[rt][1]; while(son[k][0])k=son[k][0];sz[k]+=sz[son[x][0]]; fa[son[x][0]]=k; son[k][0]=son[x][0];rt=son[x][1]; } fa[rt]=0;splay(k,rt); } void debug(){ printf("%d ",val[rt]); } int main(){ scanf("%d",&m); Insert(0x7fffffff);Insert(-0x7fffffff); int op,x; while(m--){ scanf("%d%d",&op,&x); if(op==0)Insert(x); if(op==1)del(x); if(op==2)printf("%d\n",val[find2(x)]); if(op==3){ find1(x); int ans=sz[son[rt][0]]-1; if(val[rt]<x)ans+=cnt[rt]; printf("%d\n",ans); } if(op==4){ int w=val[nxt(x,0)]; if(w==INF||w==-INF)puts("-1"); else printf("%d\n",w); } if(op==5){ int w=val[nxt(x,1)]; if(w==INF||w==-INF)puts("-1"); else printf("%d\n",w); } } return 0; }