题目大意:
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
思路:
直接splay
今天才敲。。。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 100100 12 #define MOD 1000000007 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int ch[MAXN][2],fa[MAXN],sz,cnt[MAXN],val[MAXN],size[MAXN],rt; 22 int which(int x) {return x==ch[fa[x]][1];} 23 int find_pre() 24 { 25 int pos=ch[rt][0]; 26 while(ch[pos][1]) pos=ch[pos][1]; 27 return pos; 28 } 29 int find_sub() 30 { 31 int pos=ch[rt][1]; 32 while(ch[pos][0]) pos=ch[pos][0]; 33 return pos; 34 } 35 void upd(int x) 36 { 37 if(!x) return ; 38 size[x]=cnt[x]+size[ch[x][1]]+size[ch[x][0]]; 39 } 40 void rotate(int pos) 41 { 42 int f=fa[pos],ff=fa[f],k=which(pos); 43 ch[f][k]=ch[pos][k^1],fa[ch[f][k]]=f,fa[f]=pos,ch[pos][k^1]=f,fa[pos]=ff; 44 if(ff) ch[ff][ch[ff][1]==f]=pos; 45 upd(f);upd(pos); 46 } 47 void splay(int x) 48 { 49 for(int f;f=fa[x];rotate(x)) 50 if(fa[f]) rotate((which(x)==which(f)?f:x)); 51 rt=x; 52 } 53 void Insert(int x) 54 { 55 int pos=rt,f=0; 56 while(1) 57 { 58 if(val[pos]==x) {cnt[pos]++,upd(pos);upd(f);splay(pos);return ;} 59 f=pos,pos=ch[pos][x>val[pos]]; 60 if(!pos) 61 { 62 ch[++sz][0]=ch[sz][1]=0,fa[sz]=f,val[sz]=x,cnt[sz]=size[sz]=1,ch[f][x>val[f]]=sz; 63 upd(f);splay(sz);return ; 64 } 65 } 66 } 67 void insert(int x) 68 { 69 if(!rt) {val[++sz]=x,ch[sz][0]=ch[sz][1]=fa[sz]=0,cnt[sz]=size[sz]=1,rt=sz;return;} 70 Insert(x); 71 } 72 int find_rank(int x) 73 { 74 int res=0,pos=rt; 75 while(1) 76 { 77 if(x<val[pos]) pos=ch[pos][0]; 78 else 79 { 80 res+=size[ch[pos][0]]; 81 if(val[pos]==x) {splay(pos);return res+1;} 82 res+=cnt[pos],pos=ch[pos][1]; 83 } 84 } 85 } 86 int find_num(int x) 87 { 88 int tmp=0,pos=rt; 89 while(1) 90 { 91 if(ch[pos][0]&&x<=size[ch[pos][0]]) pos=ch[pos][0]; 92 else 93 { 94 tmp=size[ch[pos][0]]+cnt[pos]; 95 if(x<=tmp) return val[pos]; 96 x-=tmp,pos=ch[pos][1]; 97 } 98 } 99 } 100 void dlt(int x) 101 { 102 find_rank(x); 103 if(cnt[rt]>1) {cnt[rt]--;return ;} 104 if(!ch[rt][0]&&!ch[rt][1]) {rt=0;return ;} 105 if(!ch[rt][0]||!ch[rt][1]) 106 { 107 int k=!ch[rt][1]?0:1; 108 rt=ch[rt][k],fa[rt]=0; 109 return ; 110 } 111 int k=find_pre(),tmp=rt; 112 splay(k);fa[ch[tmp][1]]=rt; 113 ch[rt][1]=ch[tmp][1],rt=k; 114 } 115 int main() 116 { 117 int T=read(),opt,x; 118 while(T--) 119 { 120 opt=read(),x=read(); 121 if(opt==1) insert(x); 122 if(opt==2) dlt(x); 123 if(opt==3) printf("%d\n",find_rank(x)); 124 if(opt==4) printf("%d\n",find_num(x)); 125 if(opt==5) {insert(x);printf("%d\n",val[find_pre()]);dlt(x);} 126 if(opt==6) {insert(x);printf("%d\n",val[find_sub()]);dlt(x);} 127 } 128 }