★★★   输入文件:phs.in   输出文件:phs.out   简单对比
                  时间限制:1 s   内存限制:128 MB

【题目描述】

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

【输入格式】

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

【输出格式】

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

【样例输入】

  1. 10
  2. 1 106465
  3. 4 1
  4. 1 317721
  5. 1 460929
  6. 1 644985
  7. 1 84185
  8. 1 89851
  9. 6 81968
  10. 1 492737
  11. 5 493598

【样例输出】

  1. 106465
  2. 84185
  3. 492737

【提示】

1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]

  SBT版的:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=;
  4. int root,tot,N;
  5. int key[maxn],siz[maxn],lc[maxn],rc[maxn];
  6. void r_rotate(int &rt){
  7. int k=lc[rt];
  8. lc[rt]=rc[k];
  9. rc[k]=rt;
  10. siz[k]=siz[rt];
  11. siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
  12. rt=k;
  13. }
  14. void l_rotate(int &rt){
  15. int k=rc[rt];
  16. rc[rt]=lc[k];
  17. lc[k]=rt;
  18. siz[k]=siz[rt];
  19. siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
  20. rt=k;
  21. }
  22. void MAINTAIN(int &rt,bool flag){
  23. if(flag==false){//rt的左子树的某子树>rt的右子树
  24. if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);//如果rt的左孩子的左孩子>rt的右孩子,rt右旋
  25. else if(siz[rc[lc[rt]]]>siz[rc[rt]]){//如果rt的左孩子L的右孩子B > rt的右孩子R:
  26. l_rotate(lc[rt]);//先让rt的左孩子左旋,使rt的左子树变成以B为根
  27. r_rotate(rt);//再右旋再变成以B为根
  28. }
  29. else return;//平衡
  30. }
  31. else{//rt的右子树的某子树>rt的左子树
  32. if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
  33. else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
  34. r_rotate(rc[rt]);
  35. l_rotate(rt);
  36. }
  37. else return;
  38. }
  39. MAINTAIN(lc[rt],); MAINTAIN(rc[rt],);//检查是否满足平衡
  40. MAINTAIN(rt,); MAINTAIN(rt,);
  41. }
  42. void insert(int &rt,int v){
  43. if(rt==){//找到合适的位置插入
  44. rt=++tot;
  45. key[rt]=v;
  46. lc[rt]=rc[rt]=; siz[rt]=;
  47. return ;
  48. }
  49. siz[rt]++;
  50. if(v<=key[rt]) insert(lc[rt],v);
  51. else insert(rc[rt],v);
  52. MAINTAIN(rt,v>key[rt]);//调整树结构
  53. }
  54. int Delete(int &rt,int v){
  55. int ans;
  56. siz[rt]--;
  57. if(v==key[rt]||(v<key[rt]&&lc[rt]==)||(v>key[rt]&&rc[rt]==)){
  58. ans=key[rt];
  59. if(lc[rt]==||rc[rt]==) rt=lc[rt]+rc[rt];//没有左子树或者右子树,直接利用&操作,相当于直接以子树接到上个节点
  60. else key[rt]=Delete(lc[rt],key[rt]+);//返回左子树中的最大值,然后替换当前的rt,相当于删掉当前节点,用左子树中最大值放在这个位置来代替
  61. return ans;
  62. }
  63. if(v<key[rt]) ans=Delete(lc[rt],v);
  64. else ans=Delete(rc[rt],v);
  65. return ans;
  66. }
  67. bool find(int &rt,int v){//查找是否有 key值为 v的节点
  68. if(rt==) return false;
  69. else if(v==key[rt]) return true;
  70. else if(v<key[rt]) return find(lc[rt],v);
  71. else if(v>key[rt]) return find(rc[rt],v);
  72. }
  73. int rank(int &rt,int v){//询问排名
  74. if(rt==) return ;
  75. if(v<=key[rt]) return rank(lc[rt],v);
  76. else return siz[lc[rt]]++rank(rc[rt],v);
  77. }
  78. /*
  79. 如果元素唯一的话,可以这么写:
  80. int rank(int &rt,int v){
  81. if(rt==0) return 1;
  82. if(v==key[rt]) return siz[lc[rt]]+1;
  83. if(v<key[rt]) return rank(lc[rt],v);
  84. return siz[lc[rt]]+1+rank(rc[rt],v);
  85. }
  86. 但此题不行
  87. */
  88. int select(int &rt,int k){//返回在v位置上的节点,可以改造成取大和取小函数
  89. if(k==siz[lc[rt]]+) return key[rt];
  90. if(k<=siz[lc[rt]]) return select(lc[rt],k);
  91. else return select(rc[rt],k--siz[lc[rt]]);
  92. }
  93. int pred(int &rt,int v){//返回比 v小的最大的数
  94. if(rt==) return v;//要求是比v小,返回v的意思是没找到
  95. if(v<=key[rt]) return pred(lc[rt],v);//key[rt]>v 必然要往更小的方向,即rt的左子树
  96. else{//此时 key[rt]<v,而rt的右子树的key值都大于key[rt]
  97. int ans=pred(rc[rt],v);
  98. if(ans==v) return key[rt];//返回v表示rt的右子树中的key都比v大,返回key[rt]
  99. return ans;
  100. }
  101. }
  102. int succ(int &rt,int v){//返回比v大的最小的数
  103. if(rt==) return v;
  104. if(v>=key[rt]) return succ(rc[rt],v);
  105. else{
  106. int ans=succ(lc[rt],v);
  107. if(ans==v) return key[rt];
  108. return ans;
  109. }
  110. }
  111. void inorder(int rt){//输出中序遍历
  112. if(rt!=){
  113. inorder(lc[rt]);
  114. cout<<key[rt]<<" ";
  115. inorder(rc[rt]);
  116. }
  117. }
  118. int main(){
  119. siz[]=root=tot=;
  120. scanf("%d",&N);
  121. for(int i=,kin,num;i<=N;i++){
  122. scanf("%d%d",&kin,&num);
  123. if(kin==) insert(root,num);
  124. else if(kin==) Delete(root,num);
  125. else if(kin==) printf("%d\n",rank(root,num));
  126. else if(kin==) printf("%d\n",select(root,num));
  127. else if(kin==) printf("%d\n",pred(root,num));
  128. else if(kin==) printf("%d\n",succ(root,num));
  129. }
  130. return ;
  131. }

无注释版的:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=;
  4. int root,tot,N;
  5. int key[maxn],siz[maxn],lc[maxn],rc[maxn];
  6. void r_rotate(int &rt){
  7. int k=lc[rt];
  8. lc[rt]=rc[k];
  9. rc[k]=rt;
  10. siz[k]=siz[rt];
  11. siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
  12. rt=k;
  13. }
  14. void l_rotate(int &rt){
  15. int k=rc[rt];
  16. rc[rt]=lc[k];
  17. lc[k]=rt;
  18. siz[k]=siz[rt];
  19. siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
  20. rt=k;
  21. }
  22. void MAINTAIN(int &rt,bool flag){
  23. if(flag==false){
  24. if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);
  25. else if(siz[rc[lc[rt]]]>siz[rc[rt]]){
  26. l_rotate(lc[rt]);
  27. r_rotate(rt);
  28. }
  29. else return;
  30. }
  31. else{
  32. if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
  33. else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
  34. r_rotate(rc[rt]);
  35. l_rotate(rt);
  36. }
  37. else return;
  38. }
  39. MAINTAIN(lc[rt],); MAINTAIN(rc[rt],);
  40. MAINTAIN(rt,); MAINTAIN(rt,);
  41. }
  42. void insert(int &rt,int v){
  43. if(rt==){
  44. rt=++tot;
  45. key[rt]=v;
  46. lc[rt]=rc[rt]=; siz[rt]=;
  47. return ;
  48. }
  49. siz[rt]++;
  50. if(v<=key[rt]) insert(lc[rt],v);
  51. else insert(rc[rt],v);
  52. MAINTAIN(rt,v>key[rt]);
  53. }
  54. int Delete(int &rt,int v){
  55. int ans;
  56. siz[rt]--;
  57. if(v==key[rt]||(v<key[rt]&&lc[rt]==)||(v>key[rt]&&rc[rt]==)){
  58. ans=key[rt];
  59. if(lc[rt]==||rc[rt]==) rt=lc[rt]+rc[rt];
  60. else key[rt]=Delete(lc[rt],key[rt]+);
  61. return ans;
  62. }
  63. if(v<key[rt]) ans=Delete(lc[rt],v);
  64. else ans=Delete(rc[rt],v);
  65. return ans;
  66. }
  67. bool find(int &rt,int v){
  68. if(rt==) return false;
  69. else if(v==key[rt]) return true;
  70. else if(v<key[rt]) return find(lc[rt],v);
  71. else if(v>key[rt]) return find(rc[rt],v);
  72. }
  73. int rank(int &rt,int v){
  74. if(rt==) return ;
  75. if(v<=key[rt]) return rank(lc[rt],v);
  76. else return siz[lc[rt]]++rank(rc[rt],v);
  77. }
  78. int select(int &rt,int k){
  79. if(k==siz[lc[rt]]+) return key[rt];
  80. if(k<=siz[lc[rt]]) return select(lc[rt],k);
  81. else return select(rc[rt],k--siz[lc[rt]]);
  82. }
  83. int pred(int &rt,int v){
  84. if(rt==) return v;
  85. if(v<=key[rt]) return pred(lc[rt],v);
  86. else{
  87. int ans=pred(rc[rt],v);
  88. if(ans==v) return key[rt];
  89. return ans;
  90. }
  91. }
  92. int succ(int &rt,int v){
  93. if(rt==) return v;
  94. if(v>=key[rt]) return succ(rc[rt],v);
  95. else{
  96. int ans=succ(lc[rt],v);
  97. if(ans==v) return key[rt];
  98. return ans;
  99. }
  100. }
  101. void inorder(int rt){
  102. if(rt!=){
  103. inorder(lc[rt]);
  104. cout<<key[rt]<<" ";
  105. inorder(rc[rt]);
  106. }
  107. }
  108. int main(){
  109. siz[]=root=tot=;
  110. scanf("%d",&N);
  111. for(int i=,kin,num;i<=N;i++){
  112. scanf("%d%d",&kin,&num);
  113. if(kin==) insert(root,num);
  114. else if(kin==) Delete(root,num);
  115. else if(kin==) printf("%d\n",rank(root,num));
  116. else if(kin==) printf("%d\n",select(root,num));
  117. else if(kin==) printf("%d\n",pred(root,num));
  118. else if(kin==) printf("%d\n",succ(root,num));
  119. }
  120. return ;
  121. }

  Splay版的:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<vector>
  8. using namespace std;
  9. const int maxn=;
  10. int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
  11. int tot,root;
  12. int T;
  13. void update(int x){
  14. siz[x]=siz[lc[x]]++siz[rc[x]];
  15. }
  16. void r_rotate(int x){
  17. int y=fa[x];
  18. lc[y]=rc[x];
  19. if(rc[x]!=) fa[rc[x]]=y;
  20. fa[x]=fa[y];
  21. if(y==lc[fa[y]]) lc[fa[y]]=x;
  22. else rc[fa[y]]=x;
  23. fa[y]=x; rc[x]=y;
  24. update(x); update(y);
  25. }
  26. void l_rotate(int x){
  27. int y=fa[x];
  28. rc[y]=lc[x];
  29. if(lc[x]!=) fa[lc[x]]=y;
  30. fa[x]=fa[y];
  31. if(y==lc[fa[y]]) lc[fa[y]]=x;
  32. else rc[fa[y]]=x;
  33. fa[y]=x; lc[x]=y;
  34. update(x); update(y);
  35. }
  36. void splay(int x,int s){
  37. int p;
  38. while(fa[x]!=s){
  39. p=fa[x];
  40. if(fa[p]==s){
  41. if(x==lc[p]) r_rotate(x);
  42. else l_rotate(x);
  43. break;
  44. }
  45. if(x==lc[p]){
  46. if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
  47. else r_rotate(x),l_rotate(x);
  48. }
  49. else{
  50. if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
  51. else l_rotate(x),r_rotate(x);
  52. }
  53. }
  54. if(s==) root=x;
  55. update(x);
  56. }
  57. int find(int v){//查找在这棵树中键值为v的节点
  58. int x=root;
  59. while(x!=){
  60. if(v<key[x]) x=lc[x];
  61. else if(v>key[x]) x=rc[x];
  62. else if(v==key[x]){
  63. splay(x,);
  64. return x;
  65. }
  66. }
  67. return -;
  68. }
  69. void New_node(int &x,int fath,int v){//建立新节点
  70. x=++tot;
  71. lc[x]=rc[x]=; siz[x]=;
  72. fa[x]=fath;
  73. key[x]=v;
  74. }
  75. void insert(int v){//插入新节点
  76. if(root==){
  77. New_node(rc[],,v);
  78. root=tot;
  79. return ;
  80. }
  81. int p,x=root;
  82. while(x!=){
  83. p=x;
  84. if(v<=key[x]) siz[x]++,x=lc[x];
  85. else siz[x]++,x=rc[x];
  86. }
  87. if(v<=key[p]) New_node(lc[p],p,v);
  88. else New_node(rc[p],p,v);
  89. splay(tot,);
  90. }
  91. int getmax(int x){//找到以x为根的最大值
  92. if(rc[x]!=) return getmax(rc[x]);
  93. return x;
  94. }
  95. int getmin(int x){//找到以x为根的最小值
  96. if(lc[x]!=) return getmin(lc[x]);
  97. return x;
  98. }
  99. int getpre(int x){//找到节点x的前驱
  100. splay(x,);
  101. return getmax(lc[x]);
  102. }
  103. int getne(int x){//找到节点x的后继
  104. splay(x,);
  105. return getmin(rc[x]);
  106. }
  107. void Delete(int v){
  108. int x=find(v);
  109. int pp=getmax(lc[x]);
  110. int nn=getmin(rc[x]);
  111. if(lc[x]==||rc[x]==){
  112. if(lc[x]==&&rc[x]==){
  113. root=; rc[]=;
  114. return ;
  115. }
  116. if(lc[x]==){
  117. rc[]=rc[x]; fa[rc[x]]=; root=rc[x]; rc[x]=;
  118. siz[x]=;
  119. return ;
  120. }
  121. else{
  122. rc[]=lc[x]; fa[lc[x]]=; root=lc[x]; lc[x]=;
  123. siz[x]=;
  124. return ;
  125. }
  126. }
  127. splay(pp,);
  128. splay(nn,root);
  129. fa[lc[nn]]=; siz[lc[nn]]=; lc[nn]=;
  130. update(nn); update(pp);
  131. }
  132. int rank(int rt,int v){//返回键值为v的节点的排名
  133. if(rt==) return ;
  134. if(v<=key[rt]) return rank(lc[rt],v);
  135. else return siz[lc[rt]]++rank(rc[rt],v);
  136. }
  137. int findkth(int x,int k){//在以x为根的树中找第 k大
  138. if(siz[lc[x]]+==k) return key[x];
  139. if(siz[lc[x]]+>k) return findkth(lc[x],k);
  140. return findkth(rc[x],k-siz[lc[x]]-);
  141. }
  142.  
  143. int pred(int rt,int v){//返回比 v小的最大的数
  144. if(rt==) return v;
  145. if(v<=key[rt]) return pred(lc[rt],v);
  146. else{
  147. int ans=pred(rc[rt],v);
  148. if(ans==v) return key[rt];
  149. return ans;
  150. }
  151. }
  152. int succ(int rt,int v){//返回比 v大的最小的数
  153. if(rt==) return v;
  154. if(v>=key[rt]) return succ(rc[rt],v);
  155. else{
  156. int ans=succ(lc[rt],v);
  157. if(ans==v) return key[rt];
  158. return ans;
  159. }
  160. }
  161. int main(){
  162. freopen("phs.in","r",stdin);
  163. freopen("phs.out","w",stdout);
  164. scanf("%d",&T);
  165. while (T--){
  166. int kin,num;
  167. scanf("%d%d",&kin,&num);
  168. if(kin==)
  169. insert(num);//插入
  170. else if(kin==)
  171. Delete(num);//删除(若有多个相同的数,只删除一个)
  172. else if(kin==)
  173. printf("%d\n",rank(root,num));//查询num数的排名(若有多个相同的数,因输出最小的排名)
  174. else if (kin==)
  175. printf("%d\n",findkth(root,num));//查询排名为x的数
  176. else if (kin==)
  177. printf("%d\n",pred(root,num));
  178. else if (kin==)
  179. printf("%d\n",succ(root,num));
  180. }
  181. return ;
  182. }

  vector版的:

  1. #include<cstdio>
  2. #include<vector>
  3. #include<algorithm>
  4. using namespace std;
  5. const int INF=;
  6. int n;
  7. vector<int> tree;
  8. int find(int x){
  9. return lower_bound(tree.begin(),tree.end(),x)-tree.begin()+;
  10. }
  11. int main(){
  12. scanf("%d",&n);
  13. tree.reserve();
  14. for(int i=,kin,x;i<=n;i++){
  15. scanf("%d%d",&kin,&x);
  16. if(kin==) tree.insert(upper_bound(tree.begin(),tree.end(),x),x);
  17. else if(kin==) tree.erase(lower_bound(tree.begin(),tree.end(),x));
  18. else if(kin==) printf("%d\n",find(x));
  19. else if(kin==) printf("%d\n",tree[x-]);
  20. else if(kin==) printf("%d\n",*--lower_bound(tree.begin(),tree.end(),x));
  21. else if(kin==) printf("%d\n",*upper_bound(tree.begin(),tree.end(),x));
  22. }
  23. return ;
  24. }

COJS:1829. [Tyvj 1728]普通平衡树的更多相关文章

  1. cogs 1829. [Tyvj 1728]普通平衡树 权值线段树

    1829. [Tyvj 1728]普通平衡树 ★★★   输入文件:phs.in   输出文件:phs.out   简单对比时间限制:1 s   内存限制:1000 MB [题目描述] 您需要写一种数 ...

  2. [BZOJ3224]Tyvj 1728 普通平衡树

    [BZOJ3224]Tyvj 1728 普通平衡树 试题描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个) ...

  3. BZOJ 3224: Tyvj 1728 普通平衡树

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 9629  Solved: 4091[Submit][Sta ...

  4. BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 7390  Solved: 3122 [Submit][S ...

  5. BZOJ 3224: Tyvj 1728 普通平衡树 treap

    3224: Tyvj 1728 普通平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除 ...

  6. BZOJ 3224: Tyvj 1728 普通平衡树 vector

    3224: Tyvj 1728 普通平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除 ...

  7. bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 5354  Solved: 2196[Submit][Sta ...

  8. BZOJ 3224: Tyvj 1728 普通平衡树(BST)

    treap,算是模板题了...我中间还一次交错题... -------------------------------------------------------------------- #in ...

  9. [补档][Tyvj 1728]普通平衡树

    [Tyvj 1728]普通平衡树 题目 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 1. 插入x数 2. 删除x数(若有多个相同的数,因只删除一个) 3. 查询x数的 ...

随机推荐

  1. 170418、vmware 安装 centos 开启网卡自启动

    前言:CentOS虚拟机安装成功后,默认开机未启用网关,通过修改配置文件,启用网卡 开启方法如下: 1.登录系统,虚拟机安装完成后,第一次登录系统,系统只有一个账号,即超级管理员root账户,输入安装 ...

  2. 160408、SpringMVC整合Shiro

    第一步:配置web.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 -->  ...

  3. Yii框架2.0的小部件

    小部件是视图里的可重用单元. 小部件是在视图中使用的,但是可能需要使用控制器传给他的模型,比如在渲染表单的时候.比如一般的时间拾取器就可以直接砸视图里加入如下代码就可以: <?php use y ...

  4. C#中Datatable和List互相转换

    其实早就该写的,哈哈,不过今天刚想起来注册,热热手,就写一下,哈哈. 直接上内容吧: 建立一个控制台应用程序, List<students> Studentlist = new List& ...

  5. ovn-kubernetes安装指南

    Master节点的安装 1.首先在master节点安装ovs和ovn: #!/bin/bash sudo apt-get install openvswitch-common openvswitch- ...

  6. jquery prop attr

    checked比较特殊,只要设置了属性checked,不管何值都是checked的.例如:<input type="checkbox" checked><inpu ...

  7. Java集合—List(转载)

    本篇文章将集中介绍了List集合相比Collection接口增加的一些重要功能以及List集合的两个重要子类ArrayList及LinkedList. 一.List集合 List作为Collectio ...

  8. TraClus java版实现

           前一阵子我们部门接到了业务那边的一个需求.想通过用户的wifi数据计算出商场内用户最喜爱走的线路.其实说白了就是用户轨迹聚类.根据业务的需求,我们最终采用了traClus聚类算法.tra ...

  9. Mysql—(2)—

    数据库存储引擎 (更多详见) 一 什么是存储引擎 mysql中建立的库===>文件夹 库中建立的表===>文件 现实生活中我们用来存储数据的文件应该有不同的类型:比如存文本用txt类型,存 ...

  10. Embedding SQLite in a c programm

    Embedding SQLite in a c programm        The following program demonstrates how to embed SQLite into ...