BZOJ 3224: Tyvj 1728 普通平衡树 [Splay]【数据结构】

前端之家收集整理的这篇文章主要介绍了BZOJ 3224: Tyvj 1728 普通平衡树 [Splay]【数据结构】前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3224

————————————————————————————————————————————
3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 12058 Solved: 5154
[Submit][Status][Discuss]
Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

1.n的数据范围:n<=100000

2.每个数的数据范围:[-2e9,2e9]
Source

平衡树

————————————————————————————————————————————

这两天不知怎地 一点思考能力都没有。 于是学了学Splay

其实Splay很好懂 只要知道平衡树的左旋和右旋操作,知道作用是吧一棵树做矮,就是不使它的某一条链变成。

本质还是一颗二叉树,只不过多了伸展的操作,也就是能通过左旋,右旋降低树高,保证某些操作总是在O(logn)的 不会变成O(n)。

附模板
————————————————————————————————————

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int N = 100000+7;
  5.  
  6. int root,tot;
  7. int father[N],data[N],cnt[N],value[N];
  8. int son[N][3];
  9.  
  10. inline void Rotate(int x,int w){
  11. int y=father[x];
  12. cnt[y]=cnt[y]-cnt[x]+cnt[son[x][w]];
  13. cnt[x]=cnt[x]-cnt[son[x][w]]+cnt[y];
  14. son[y][3-w]=son[x][w];
  15. if(son[x][w]) father[son[x][w]]=y;
  16. father[x]=father[y];
  17. if(father[y]){
  18. if(y==son[father[y]][1]) son[father[y]][1]=x;
  19. else son[father[y]][2]=x;
  20. }
  21. father[y]=x;
  22. son[x][w]=y;
  23. }
  24.  
  25. inline void splay(int x){
  26. int y;
  27. while(father[x]){
  28. y=father[x];
  29. if(!father[y]){
  30. if(x==son[y][1]) Rotate(x,2);
  31. else Rotate(x,1);
  32. }
  33. else{
  34. if(y==son[father[y]][1]){
  35. if(x==son[y][1]) Rotate(y,2),Rotate(x,2);
  36. else Rotate(x,1),2);
  37. }
  38. else {
  39. if(x==son[y][2]) Rotate(y,1);
  40. else Rotate(x,1);
  41. }
  42. }
  43. }
  44. root = x;
  45. return ;
  46. }
  47.  
  48. inline int Search(int x,int w){
  49. while(data[x]!=w){
  50. if(w==data[x]) return x;
  51. if(w<data[x]) {
  52. if(!son[x][1]) break;
  53. x = son[x][1];
  54. }
  55. else {
  56. if(!son[x][2]) break;
  57. x = son[x][2];
  58. }
  59. }
  60. return x;
  61. }
  62.  
  63. inline void Insert(int w){
  64. int k,kk;bool flag;
  65. if(!tot){
  66. tot=1;
  67. father[1]=0;cnt[1]=1;data[1]=w;root=1;value[1]=1;
  68. return ;
  69. }
  70. k = Search(root,w);
  71. if(data[k]==w){
  72. value[k]++;kk=k;
  73. flag = true;
  74. }
  75. else{
  76. tot++;
  77. data[tot]=w;
  78. father[tot]=k;
  79. cnt[tot]=1;
  80. value[tot]=1;
  81. if(data[k]>w) son[k][1]=tot;
  82. else son[k][2]=tot;
  83. flag = false;
  84. }
  85. while(k){
  86. cnt[k]++;k=father[k];
  87. }
  88. if(flag) splay(kk);else splay(tot);
  89. }
  90.  
  91. inline int Extreme(int x,int w){
  92. const int lala[3]={0,2147483647,-2147483647};
  93. int k=Search(x,lala[w]),tmp;
  94. tmp = data[k];
  95. splay(k);
  96. return tmp;
  97. }
  98.  
  99. inline void del(int x){
  100. int k=Search(root,x),y;
  101. splay(k);
  102. if(data[k]==x){
  103. if(value[k]>1){
  104. value[k]--;
  105. cnt[k]--;
  106. }
  107. else if(!son[k][1]){
  108. y=son[k][2];
  109. son[k][2]=0;
  110. cnt[k]=0;
  111. data[k]=0;
  112. value[k]=0;
  113. root = y;
  114. father[root]=0;
  115. }
  116. else {
  117. father[son[k][1]]=0;
  118. y=Extreme(son[k][1],1);
  119. son[root][2]=son[k][2];
  120. cnt[root]=cnt[root]+cnt[son[k][2]];
  121. if(son[root][2])father[son[root][2]]=root;
  122. data[k]=0;son[k][1];son[k][2]=0;
  123. value[k]=0;
  124. }
  125. }
  126. }
  127.  
  128. inline int pred(int x){
  129. int k = Search(root,x);
  130. splay(k);
  131. if(data[k]<x) return data[k];
  132. return Extreme(son[k][1],1);
  133. }
  134.  
  135. inline int succ(int x){
  136. int k = Search(root,x);
  137. splay(k);
  138. if(data[k]>x) return data[k];
  139. return Extreme(son[k][2],2);
  140. }
  141.  
  142. inline int kth(int x,int w){
  143. int i=root,tmp;
  144. while(!((x>=cnt[son[i][w]]+1)&&(x<=cnt[son[i][w]]+value[i]))&&i){
  145. if(x>cnt[son[i][w]]+value[i]){
  146. x = x - cnt[son[i][w]]-value[i];
  147. i = son[i][3-w];
  148. }
  149. else i = son[i][w];
  150. }
  151. tmp = i;splay(i);
  152. return tmp;
  153. }
  154.  
  155. inline int findnum(int x){
  156. int k = Search(root,x);splay(k);
  157. root = k;
  158. return cnt[son[k][1]]+1;
  159. }
  160.  
  161. int main(){
  162. int n,op,x;
  163. scanf("%d",&n);
  164. for(int i=1;i<=n;i++){
  165. scanf("%d%d",&op,&x);
  166. if(1==op) Insert(x);
  167. else if(2==op) del(x);
  168. else if(3==op) printf("%d\n",findnum(x));
  169. else if(4==op) printf("%d\n",data[kth(x,1)]);
  170. else if(5==op) printf("%d\n",pred(x));
  171. else if(6==op) printf("%d\n",succ(x));
  172. }
  173. return 0;
  174. }

猜你在找的数据结构相关文章