浅析FHQ-treap

news/2024/12/31 17:45:14/文章来源:https://www.cnblogs.com/fush/p/18639439

前言

更好的阅读体验
默认读者会 BST 的基本操作。

节点定义

替罪羊树采用了懒惰删除的方法,不会立即删除某个点,而是在重构时不放进数组。

struct node{  int ch[2], val;  int siz1, siz2, cnt, sum;  //扣去懒惰删除的节点数量,没扣去懒惰删除的节点数量,树内相同权值的数量,子树大小。  
}d[N];  
int root, tot, stk[N], top, v[N], t;//stk 是垃圾回收  
double al = 0.75;  
#define ls(x) d[x].ch[0]  
#define rs(x) d[x].ch[1]  
int newnode(int x){  int w = top ? stk[top--] : ++tot;  return d[w].val = x, ls(w) = rs(w) = 0, d[w].cnt = 1, pushup(w), w;  
}  
void pushup(int x){  node&rt = d[x],ls = d[ls(x)],rs = d[rs(x)];  rt.siz1 = (rt.cnt > 0) + ls.siz1 + rs.siz1;  rt.siz2 = 1 + ls.siz2 + rs.siz2;  rt.sum = rt.cnt + ls.sum + rs.sum;  
}  

重构

BST 最担心的是树退化成链。
那么有个暴力的想法:
把树拍扁放进数组,然后重新构建一棵完全二叉树。
但是过多的重构会使复杂度上升,那么我们引入一个概念:\(\alpha\)
\(\alpha = \dfrac{\max(siz2_{ls}, siz2_{rs}) }{siz2_{rt}}\)
一般的平衡树都能把 \(\alpha\) 维护在 \([0.6, 0.8]\) 左右。

我们可以将 \(\max\alpha\) 设为一个数,一般为 \([0.7,0.8]\)
一般选 \(0.75\)
在某个节点的 \(\alpha > \max \alpha\) 时,我们把这个子树重构。
如果这个树 \(siz1 \le \alpha siz2\),那么我们认为它也是需要重构的。
比如这棵树:
tu

那么我们将它拍扁放进数组。
tu
然后像线段树一样重新建树。
tu

#define check(x) x&&(al*d[x].siz2<=max(d[ls(x)].siz2,d[rs(x)].siz2)||d[x].siz1<=0.75*d[x].siz2)  
void dfs(int x){  if(!x)return;  dfs(ls(x)), (d[x].cnt ? v[++t] : stk[++top]) = x, dfs(rs(x));  
}  
int build(int l, int r){  if(l == r)return ls(v[l]) = rs(v[l]) = 0, pushup(v[l]), v[l];  if(l > r)return 0;  int mid = l + r >> 1, x = v[mid];  ls(x) = build(l, mid - 1), rs(x) = build(mid + 1, r);  return pushup(x), x;  
}  
#define refactoring(x) t = 0, dfs(x), x = build(1, t)  

插入

如果在当前节点的权值和要插入的权值一样,我们将 \(cnt\) 增加。
其他和 BST 一样。
记得在回溯时更新节点,判断是否重构。

void insert(int&now, int val){  if(!now)return void(now = newnode(val));  if(d[now].val == val)d[now].cnt++;  else if(d[now].val < val)insert(rs(now), val);  else insert(ls(now), val);  pushup(now);  if(check(now))refactoring(now);  
}  

删除

懒惰删除,只是将 \(cnt\) 减少。
然后在回溯时更新节点,判断是否重构。

void del(int&now, int val){  if(!now)return;  if(d[now].val == val)d[now].cnt--;  else if(d[now].val < val)del(rs(now), val);  else del(ls(now), val);  pushup(now);  if(check(now))refactoring(now);  
}  

查询操作

这部分就差不多了。

int kth(int x){  int now = root, siz = 0, z = x;  while(now){  if((siz = d[ls(now)].sum) >= x)now = ls(now);  else if((siz += d[now].cnt) < x)x -= siz, now = rs(now);  else return d[now].val;  }  return -1;  
}  
int query_rank(int val){  int ans = 1, now = root;  while(now){  if(d[now].val == val)ans += d[ls(now)].sum, now = 0;  else if(d[now].val < val)ans += d[ls(now)].sum + d[now].cnt, now = rs(now);  else now = ls(now);  }  return ans;  
}  
int ask_pre(int val){return kth(query_rank(val) - 1);}  
int ask_next(int val){return kth(query_rank(val + 1));}  

代码

完整代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/860982.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20241313刘鸣宇《计算机基础与程序设计》第14周学习总结

2024-2025-1 20241313《计算机基础与程序设计》第14周学习总结 作业信息这个作业属于哪个课程 <班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(如2024-2025-1计算机基础与程序设计第一周作业)这个作业的目标 <写上具…

学习笔记:旋转treap

前言 更好的阅读体验。 无旋 treap。 默认读者会 BST 的基本操作、堆和旋转。 本文旋转部分和上面那篇文章的相同。 代码中是小根堆。 思想 treap 既是一棵二叉查找树(tree),也是一个二叉堆(heap)。 但是如果这两个数据结构用同一个权值维护,那么这两种数据结构是矛盾的。…

最早发明的自平衡二叉树:AVL

前言 更好的阅读体验 默认读者会基本的 BST 操作。 节点定义 平衡因子:BF(BalanceFactor),左子树高 \(-\) 右子树高。 平衡树是让树的形态尽可能像完全二叉树,而不是链。 在 AVL 中,我们认为 \(\left|\text{BF}\right|\le 1\),也就是 BF 为 \(0,1,-1\) 时的子树是平衡的,…

[COCI2015-2016#2] DRZAVA

思路 先把赛时想法搬一部分过来转化题意, 对于 \(n\) 个带权 \(k\) 的点, 任意两点 \(i, j\) 之间有双向连边, 其边权为 \(w_{i, j} = d_{i, j}\) , 求一最小阈值 \(C\) , 满足对于所有 \(w \leq C\) 的边连接后, 存在一个连通块 \(G\), 使得 \[\sum_{i = 1}^{\lvert G \rvert}…

The End

一、学期回顾 1.1 回顾你对于软件工程课程的想象 根据你对课程目标和期待,回顾目前的所学所练所得,在哪些方面达到了你的期待和目标,哪些方面还存在哪些不足,为什么? 达成的目标与期待理论与实践结合: 课程的最大目标之一是将软件工程的理论知识应用到实践中。在这一点上…

关于本站

我是 fush,一个很菜的 oier。 这里,我只想分享一些自己在学习记录。 由于本人较菜,有哪里写的不严谨的地方欢迎指出。 除了下面几个账号(本人的),如果要转载请写明出处,谢谢。 洛谷

从 Leafy-Tree 到 WBLT

更好的阅读体验。 UPD:2024/12/04 添加序列操作 UPD:2024/12/10 添加可持久化 前言 前面说过 FHQ-treap 的缺点在于常数。 这次篇文章要讲解 WBLT,码量与 FHQ-treap 差的不多,结构与线段树类似。 也可以分裂合并(不推荐),可持久化,但常数远小于 FHQ-treap。 美中不足的…

快消零售业的创新之路:智能AI助力员工培训SOP高效构建

在快速消费品零售行业,员工培训是提升服务质量、增强竞争力的重要手段。然而,传统员工培训方式往往存在培训周期长、效果难以评估等问题,难以满足快消零售行业对于高效、精准培训的需求。随着人工智能技术的不断发展,智能AI在员工培训中的应用逐渐受到重视,特别是在构建员…

django rest framework 视图类关系图

纸上得来终觉浅,绝知此事要躬行

挖掘内部知识库在员工培训与发展中的巨大潜力

在当今快速变化的商业环境中,企业的核心竞争力越来越依赖于其员工的技能水平和持续学习能力。员工培训与发展不再是简单的技能传授,而是需要构建一个能够激发潜能、促进知识共享与创新的智慧学习生态。内部知识库,作为这一生态的核心组成部分,其潜力在员工培训与发展中日益…

数学专题 2024.12

数学专题 2024.12 Luogu 3175 按位或 刚开始你有一个数字 \(0\),每一秒钟你会随机选择一个 \([0,2^n-1]\) 的数字,与你手上的数字进行或(C++,C 的 |,pascal 的 or)操作。选择数字 \(i\) 的概率是 \(p_i\)。保证 \(0\leq p_i \leq 1\),\(\sum p_i=1\) 。问期望多少秒后,你…

AGENT AI-surveying the horizons of multimodal interaction

(转自https://www.cnblogs.com/hifrank/p/18416222) 标题:AGENT AI: surveying the horizons of multimodal interaction作者:Zane Durante, Qiuyuan Huang, Naoki Wake, Ran Gong, Jae Sung Park, Bidipta Sarkar, Rohan Taori, Yusuke Noda, Demetri Terzopoulos, Yejin …