1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. #define alpha 0.8
  6. #define maxn 2000001
  7. #define ri register
  8. #define il inline
  9. using namespace std;
  10. struct scapegoat{
  11. int son[2], val, valid, total;//valid(有效的)未被删除的子树的点数 total(总数)子树总点数
  12. bool exist;//是否要被删除 exist(存在)1表示未被删除 0表示被删除
  13. }e[maxn];
  14. int memory[maxn]; //内存池
  15. int cur[maxn]; //拍扁的时候用的内存空间
  16. int root, pool, poi, cnt, to_rebuild;
  17. il bool isbad(int now)
  18. {
  19. if((double)e[now].valid*alpha <= (double)max(e[e[now].son[0]].valid, e[e[now].son[1]].valid)) return true;
  20. return false;
  21. }
  22. void dfs(int now) // 中序遍历,找出要被拍扁的节点的编号
  23. {
  24. if(!now) return;
  25. dfs(e[now].son[0]);
  26. if(e[now].exist) cur[++poi] = now;
  27. else memory[++pool] = now;
  28. dfs(e[now].son[1]);
  29. }
  30. void build(int l, int r, int &now) //你建树值要跟着变的...now当然加&了...
  31. {
  32. int mid = l+r>>1;//其实建树的序列已经按顺序保存在cur里了,你只需要改变父子关系就行
  33. now = cur[mid];//cur里存的是编号.把中间的元素取出来,中间元素的编号为now.
  34. if(l == r)//只造一个节点..?
  35. {
  36. e[now].son[0] = e[now].son[1] = 0;
  37. e[now].total = e[now].valid = 1;
  38. return;
  39. }
  40. if(l < mid) build(l,mid-1,e[now].son[0]);//到mid-1是因为mid已经建完了
  41. else e[now].son[0] = 0;
  42. build(mid+1,r,e[now].son[1]);//左右递归建树
  43. e[now].total = e[e[now].son[0]].total + e[e[now].son[1]].total + 1;//更新节点信息
  44. e[now].valid = e[e[now].son[0]].valid + e[e[now].son[1]].valid + 1;
  45. }
  46. il void rebuild(int &now)
  47. {
  48. poi = 0;//别忘了你重建的子树要从头开始算啊,不清零..就听取WA声一片
  49. dfs(now);//中序遍历一遍
  50. if(poi) build(1,poi,now);
  51. else now = 0;
  52. }
  53. il int find_rank(int k)//寻找k的排名
  54. {
  55. int now = root;
  56. int ans = 1;
  57. while(now)
  58. {
  59. if(e[now].val >= k) now = e[now].son[0];
  60. else
  61. {
  62. ans += e[e[now].son[0]].valid + e[now].exist;//+e[now].exist是因为我相同大小的节点虽然放在一起,但是我不知道我这个节点上相同的我是不是还存在啊..所以我得单独加我..至于valid是除我以外的子树大小。
  63. now = e[now].son[1];
  64. }
  65. }
  66. return ans;
  67. }
  68. il int find_kth(int k)
  69. {
  70. int now = root;
  71. while(now)
  72. {
  73. if(e[now].exist&&e[e[now].son[0]].valid+1 == k) return e[now].val;
  74. else if(e[e[now].son[0]].valid >= k) now = e[now].son[0];
  75. else
  76. {
  77. k -= e[e[now].son[0]].valid + e[now].exist;
  78. now = e[now].son[1];
  79. }
  80. }
  81. }
  82. void insert(int &now, int val)
  83. {
  84. if(!now)//找到一个插入的位置
  85. {
  86. now = memory[pool--]; e[now].val = val;
  87. e[now].exist = e[now].total = e[now].valid = 1;
  88. e[now].son[0] = e[now].son[1] = 0;
  89. return;
  90. }
  91. e[now].total++, e[now].valid++;//一边向下一边更新,这点与spaly不同
  92. if(e[now].val >= val) insert(e[now].son[0], val);
  93. else insert(e[now].son[1], val);
  94. if(!isbad(now))
  95. {
  96. if(to_rebuild)
  97. {
  98. if(e[now].son[0] == to_rebuild) rebuild(e[now].son[0]);
  99. else rebuild(e[now].son[1]);
  100. to_rebuild = 0;
  101. }
  102. }
  103. else to_rebuild = now;
  104. }
  105. il void delete_pos(int &now, int tar) //target(目标)
  106. {
  107. if(e[now].exist&&e[e[now].son[0]].valid+ 1 == tar)//删除位置为tar的..
  108. {
  109. e[now].exist = 0; e[now].valid--; return;
  110. }
  111. e[now].valid--;
  112. if(e[e[now].son[0]].valid + e[now].exist >= tar) delete_pos(e[now].son[0], tar);
  113. else delete_pos(e[now].son[1],tar-e[e[now].son[0]].valid-e[now].exist);
  114. }
  115. il void delete_val(int tar)
  116. {
  117. delete_pos(root, find_rank(tar));
  118. if((double)e[root].total*alpha > e[root].valid) rebuild(root);
  119. }
  120. int main()
  121. {
  122. int opt, x, m;
  123. for(int i = 2000000; i >= 1; i--) memory[++pool] = i;
  124. scanf("%d",&m);
  125. while(m--)
  126. {
  127. scanf("%d%d",&opt,&x);
  128. if(opt == 1) {insert(root, x);}
  129. if(opt == 2) {delete_val(x);}
  130. if(opt == 3) {printf("%d\n",find_rank(x));}
  131. if(opt == 4) {printf("%d\n",find_kth(x));}
  132. if(opt == 5) {printf("%d\n",find_kth(find_rank(x)-1));}
  133. if(opt == 6) {printf("%d\n",find_kth(find_rank(x+1)));}
  134. }
  135. //哇这太恐怖了我的替罪羊树他还能查没有插入的节点的排名...(好像是对于没插入过的节点会假装插进去了查询一个排名..但下次操作不会当做真插入了来做)
  136. return 0;
  137. }

【luogu P3369 【模板】普通平衡树(Treap/SBT)】 模板 Scapegoat Tree的更多相关文章

  1. luoguP3369[模板]普通平衡树(Treap/SBT) 题解

    链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...

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

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

  3. 平衡树 替罪羊树(Scapegoat Tree)

    替罪羊树(Scapegoat Tree) 入门模板题 洛谷oj P3369 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入xx数 删除xx数(若有多个相同 ...

  4. 【模板】平衡树——Treap和Splay

    二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值.且左右子树也分别是二叉搜索树.(如下) $BST$的作用:维护一个有序数列,支持插入$x$ ...

  5. [luogu P3369]【模板】普通平衡树(Treap/SBT)

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

  6. 数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

    二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) #include <cstdio> #define Max 100005 #define Inline _ ...

  7. 替罪羊树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

    二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 闲的没事,把各种平衡树都写写 比较比较... 下面是替罪羊树 #include <cstdio> #inc ...

  8. 红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

    二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 近几天闲来无事...就把各种平衡树都写了一下... 下面是红黑树(Red Black Tree) 喜闻乐见拿到了luo ...

  9. 洛谷P3369 【模板】普通平衡树(Treap/SBT)

    洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...

  10. AC日记——【模板】普通平衡树(Treap/SBT) 洛谷 P3369

    [模板]普通平衡树(Treap/SBT) 思路: 劳资敲了一个多星期: 劳资终于a了: 劳资一直不a是因为一个小错误: 劳资最后看的模板: 劳资现在很愤怒: 劳资不想谈思路!!! 来,上代码: #in ...

随机推荐

  1. lua实现List及Dictionary

    转载:http://www.maosongliang.com/archives/122 参考 http://blog.csdn.net/jason_520/article/details/541736 ...

  2. 腾讯刘金明:腾讯云 EB 级对象存储架构深度剖析及实践

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 演讲者:刘金明 腾讯云存储业务中心副总监 背景:5月23-24日,以"焕启"为主题的腾讯"云+未来" ...

  3. 百度地图api-动态添加覆盖物

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  4. angular2 遇到的问题汇总

    angular2 学习资源集锦:https://github.com/timjacobi/angular2-education 在学习angular开发项目过程遇到的问题: 1. 不同componen ...

  5. 【Linux相识相知】bash的特性

    命令历史 shell进程会记录用户提交执行过的命令 可以是用history查看: [root@localhost dev]# history ss -tnl ifconfig vi /etc/sysc ...

  6. UML建模—EA的使用起步

    Enterprise Architect(EA) 是一个功能比较强悍的建模工具. 对于一个软件设计者来说,从需求分析到业务设计.类模型设计.数据库设计到测试.发布.部署等一系列软件设计必须的操作都可以 ...

  7. 我们能用canvas做什么?

    什么是Canvas? Canvas元素是HTML5的一部分,允许脚本语言动态渲染位图像.Canvas由一个可绘制地区HTML代码中的属性定义决定高度和宽度.JavaScript代码可以访问该地区,通过 ...

  8. sp 数据拼接html table表转换xml,发邮件

    USE [BES_ADV] GO /****** Object: StoredProcedure [dbo].[RSP_FN_UNAPPLIED_Mail_Reminder] Script Date: ...

  9. bootstrap清除数据源

    下拉框使用动态数据源,当下拉框触发change事件时,想让下拉框改变数据源,加了个if判断 $('#@idForCostCategory').change(function (event) { if( ...

  10. [LeetCode]21. Merge Two Sorted Lists合并两个有序链表

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...