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. 案例46-crm练习客户登录

    1 login.jsp代码 <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  2. 《springcloud 四》服务保护机制

    服务保护机制SpringCloud Hystrix 微服务高可用技术 大型复杂的分布式系统中,高可用相关的技术架构非常重要. 高可用架构非常重要的一个环节,就是如何将分布式系统中的各个服务打造成高可用 ...

  3. Scala安装及开发环境搭建

    最近想学习下scala,为后面转大数据做一些沉淀. 1. 首先保证jdk已经成功安装 2. 去官网下载scala安装程序 http://www.scala-lang.org/download/all. ...

  4. sqlite3在别的目录写文件的问题

    今天碰到一个文件,就是sqlite数据不能把db创建在别的目录下.找了好久不得其解.后来换了一个sqlite jar包就好了. 原来我用的是sqlite-nested 内嵌的jar包. 换成这里的包h ...

  5. 深入理解Javascript封装DOMContentLoaded事件

    最近在写一个Javascript的框架,刚把DOMContentLoaded事件封装好,略带小兴奋,把开发过程中遇到的原理和兼容性问题做篇笔记,省的忘记到处找. 我们在写js代码的时候,一般都会添加w ...

  6. [转]ASP.NET MVC 5 List Editor with Bootstrap Modals

    本文转自:https://www.codeproject.com/articles/786085/asp-net-mvc-list-editor-with-bootstrap-modals With ...

  7. 网站部署中遇到的问题-网页中js,css和图片资源无法加载

    问题描述: 打开的网页跑版,图片无法加载,用控制台调试发现css和js都没有加载. 原因: 没有启用IIS"静态内容". 解决方法: 设置"打开或关闭windows功能& ...

  8. vs文件属性(复制到输出目录)是什么意思

    右击项目里的文件,选择属性(F4)会有复制到输出目录的选项. 它提供三项选择,如图: 如果选择始终复制或如果较新则复制会在该程序集的bin目录下生成该文件,如图:

  9. 04.Dictionary字典键值对集合

    Dictionary字典键值对集合和Hashtable键值对集合的功能非常类似, 只是在声明的时候,必须为其制定值的类型. 示例代码: namespace _11.Dictionary字典集合的学习 ...

  10. bootstrap模态框实现相对定位拖拽

    1.正常的拖拽是用绝对定位absolute来实现的,可是bootstrap的模态框是用relative,为了统一更改方便,就照着相对定位来实现拖拽效果. $(".modal .modal-h ...