首页 > 其他分享 >优雅的暴力:替罪羊树

优雅的暴力:替罪羊树

时间:2024-12-29 19:08:44浏览次数:1  
标签:return 暴力 val rs int 替罪羊 优雅 ls now

前言

本文无大错误不再更新,会更新在博客
默认读者会 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));}  

代码

完整代码

标签:return,暴力,val,rs,int,替罪羊,优雅,ls,now
From: https://www.cnblogs.com/fush/p/18639418

相关文章

  • 「 Java基础-链式调用 」Java开发中如何让你的代码看起来更优雅?试试链式调用?
    一、前言我们日常在写业务代码的时候,经常会遇到一种场景,比如一个对象有很多属性,比如用户对象有很多属性:用户名、用户ID、用户性别、用户居住地址、用户工作类型、用户联系方式等等,当我们要构建一个用户对象的时候,就要不断的去set,get如下代码所示:publicclassUser{......
  • [响应式编程] 如何优雅Exception异常处理
    初识响应式编程的时候,除了从命令式的思维方式转变为函数式的编程方式外,其中有一个很大的不适应的地方就是在面对异常时该怎么处理,尤其是面对检查异常(CheckedException)时更是不知所措。在遇到异常时,我们通用的处理方式就是打日志、降级兜底、重试三板斧,本文通过ProjectReacto......
  • hydra 暴力破解工具
    Hydra是一款开源的暴力破解工具,由著名黑客组织THC开发。它支持多种协议和登录方法,如SSH、FTP、HTTP等,广泛用于渗透测试和安全评估。通过暴力破解、字典攻击、多线程等技术,尝试猜测和破解密码,以获取系统认证权限。1、基础用法格式hydra-LXXX.txt-PXXX.txt目标IP或网......
  • 鸿蒙OS开发秘籍:打造优雅的登录状态管理系统
    一、前言在鸿蒙OS开发过程中,随着应用规模的扩大,登录状态管理逐渐成为系统设计中的一个挑战。一个清晰、高效的登录状态管理系统不仅可以简化开发流程,还能提升用户体验。本文将分享一种优雅的登录状态管理设计方案,帮助开发者轻松应对复杂系统中的登录状态控制。二、认证事件与认......
  • 优雅驾驭 TryParse:技巧与实战全攻略
    一、引言在编程的世界里,数据类型的转换是我们经常会遇到的操作。而TryParse方法作为一种安全、高效的类型转换方式,在许多编程语言中都有着广泛的应用,比如C#、Java等。它能够帮助我们在将字符串转换为其他数据类型时,避免因格式不正确而引发的异常,使我们的程序更加健壮和稳定......
  • Python 抽象基类 ABC :从实践到优雅
    今天我们来聊聊Python中的抽象基类(AbstractBaseClass,简称ABC)。虽然这个概念在Python中已经存在很久了,但在日常开发中,很多人可能用得并不多,或者用得不够优雅。让我们从一个实际场景开始:假设你正在开发一个文件处理系统,需要支持不同格式的文件读写,比如JSON、CSV、XML等。......
  • Netty优雅退出
    Netty优雅退出|Id|Title|DateAdded|SourceUrl|PostType|Body|BlogId|Description|DateUpdated|IsMarkdown|EntryName|CreatedTime|IsActive|AutoDesc|AccessPermission||-------------|-------------|-------------|-------------|----------......
  • 《水烟水雾》d3dx9_43.dll文件丢失,优雅解决之法
    《水烟水雾》是一款充满诗意与奇幻色彩的游戏,然而,近期不少玩家在游戏过程中遇到了d3dx9_43.dll文件丢失的问题,这不仅打断了游戏的连贯性,也影响了玩家的沉浸体验。本文将为大家提供一种优雅的解决方案,帮助玩家摆脱这一困扰。1.重新安装游戏有时,游戏文件可能因各种原因而损......
  • 实时预警,防范暴力事件 | 思通数科AI监控保障监狱安全与秩序
    用户痛点介绍在监狱或看守所等高风险场所,人工监控面临着极大的挑战。由于监控人员的疲劳和视线盲区,很多潜在的暴力事件或犯罪行为往往无法被及时察觉。传统监控系统无法提供实时的数据分析,隐患往往滞后被发现,极大增加了暴力冲突或其他安全事故的发生概率。同时,传统监控系统缺乏智......
  • 【产品小白】如何优雅应对紧急需求
    目录冷静拆解真正的紧急点将“紧急项目”拆解为里程碑坚守流程,评审优先        在产品管理的世界里,紧急需求就像隐藏在暗处的“刺客”,随时可能打乱我们精心规划的工作节奏,让团队陷入混乱与忙碌之中。然而,我们必须清醒地意识到,紧急需求频繁出现绝非正常现象,它往......