平衡树 treap 模板

偷懒专用平衡树——Treap Treap的实现 阅读详情
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
//treap 就是tree+heap 利用了二叉堆的结构整体趋于平衡树(不一定是严格意义上的平衡)
//又利用了二叉平衡树的排序 才让查找 插入的效率在logn 
struct data{//该树的标号为完全二叉树标号方式 
    int l,r,v,size,rnd,w;//分别表示左右子树的序号,节点的值,
	//以该节点为根左右子树加上该点总共有多少值,节点的随机值(是建成二叉堆的依据),等于v的值有几个(因为可能有好几个相同的值) 
}tr[100005];
int n,size,root,ans;
void update(int k)//更新结点信息
{
    tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;
}
void rturn(int &k)//参考左旋 
{
    int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k;
    tr[t].size=tr[k].size;update(k);k=t;
}
void lturn(int &k)//左旋 
{
    int t=tr[k].r;
	tr[k].r=tr[t].l;//该点的右子树变成原来右子树的左子树 
	tr[t].l=k;//原来的右子树的左子树为该点 
    tr[t].size=tr[k].size;//原来右子树的大小就是为该点值的大小(好好考虑下 因为旋转了这棵树总的大小还是不变的) 
	update(k);//更新该点信息 
	k=t;//因为左旋后位置发生了改变 原来右子树的点到了该节点的位置 所以k赋值为t 
}
void insert(int &k,int x)//使用引用可直接赋值 
{     //插入肯定会最后被安排到叶子节点 
    if(k==0)//若已经到了叶子节点 
    {
        size++;k=size;//总节点数加一 给该节点标号 
        tr[k].size=tr[k].w=1;//该点的大小和w值都赋值为1 
		tr[k].v=x;
		tr[k].rnd=rand();//产生随机数并赋值 
        return;
    }
    tr[k].size++;//插入一个数 所查找经过的值都加一 因为从上往下走 一定是它的子孙会被插入添加 所以该节点也要修改 
    if(tr[k].v==x)tr[k].w++;//插入的数已经存在且就是该树 则直接在w上加一 
    else if(x>tr[k].v)//如果大于该节点值 
    {
        insert(tr[k].r,x);//向右寻找要插入的点 
        if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);//回溯的过程中如果右子树的随机值小于该随机值 则左旋 
		//而且二叉树的左旋和右旋并不影响二叉排序树的性质 又可以调整二叉堆的顺序 
    }
    else 
    {
        insert(tr[k].l,x);
        if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k);
    } 
}
/*
情况一, 该节点为叶节点或链节点(即只有一个孩子节点的节点),则该节点是可以直接删除的节点。若该节点有非空子节点,用非空子节点代替该节点的,否则用空节点代替该节点,然后删除该节点。

情况二, 该节点有两个非空子节点。我们的策略是通过旋转,使该节点变为可以直接删除的节点。如果该节点的左子节点的修正值小于右子节点的修正值,右旋该节点,使该节点降为右子树的根节点,然后访问右子树的根节点,继续讨论;反之,左旋该节点,使该节点降为左子树的根节点,然后访问左子树的根节点,继续讨论,直到变成可以直接删除的节点。(也就是让该节点的左右孩子节点中的最小优先级的节点称为该节点)*
*/ 
void del(int &k,int x)
{
    if(k==0)return; //到叶子节点直接返回 
    if(tr[k].v==x)
    {
        if(tr[k].w>1)//要删的值有好几个 
        {
            tr[k].w--;tr[k].size--;return;//直接把计数减少 
        }
        if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;//如果该节点是只有一个子节点或者没有子节点 该节点直接被子节点替代 
        else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd)//选择左右子树中最小的一个节点作为根节点 
            rturn(k),del(k,x);//先旋转 再看是否满足删除的条件 
        else lturn(k),del(k,x);
    }
    else if(x>tr[k].v)//查找 该路径上的值都要减一 
        tr[k].size--,del(tr[k].r,x);
    else tr[k].size--,del(tr[k].l,x);
}
int query_rank(int k,int x)//查询x的排名  就是把小于自己的树(左子树)的综合加上自身(加1) 
{
    if(k==0)return 0; 
    if(tr[k].v==x)return tr[tr[k].l].size+1;//找到了该节点 把左子树的个数加上自身的个数(只加一 因为只要求最小的那个值)  
    else if(x>tr[k].v)//如果大于该数将此节点的左子树和本身节点的w加起来再去右子树中找小于该数的数 
        return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x);
    else return query_rank(tr[k].l,x);//如果x小于当前节点从左子树找 
}
int query_num(int k,int x)//查询排名为x的数 
{
    if(k==0)return 0;
    if(x<=tr[tr[k].l].size)//如果x比左子树的总和小就往左子树里找 
        return query_num(tr[k].l,x);
    else if(x>tr[tr[k].l].size+tr[k].w)// 如果比该节点的左子树和该点w的总和大往右子树找第x-tr[tr[k].l].size-tr[k].w个值 
        return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w);
    else return tr[k].v;//刚好缩到为1的时候的那个值就是查的那个值 
}
void query_pro(int k,int x)//查找该x的前驱 小于x的最大值 
{
    if(k==0)return;
    if(tr[k].v<x)//查找遍历的过程中记录路径上小于x的值 最后一个一定是小于他的最大值 
    {
        ans=k;//ans记录最优解 
		query_pro(tr[k].r,x);
    }
    else query_pro(tr[k].l,x);
}
void query_sub(int k,int x)//同上 
{
    if(k==0)return;
    if(tr[k].v>x)
    {
        ans=k;query_sub(tr[k].l,x);
    }
    else query_sub(tr[k].r,x);
}
int main()
{
    scanf("%d",&n);
    int opt,x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&opt,&x);
        switch(opt)
        {
        case 1:insert(root,x);break; //root=1 
        case 2:del(root,x);break;
        case 3:printf("%d\n",query_rank(root,x));break;
        case 4:printf("%d\n",query_num(root,x));break;
        case 5:ans=0;query_pro(root,x);printf("%d\n",tr[ans].v);break;
        case 6:ans=0;query_sub(root,x);printf("%d\n",tr[ans].v);break;
        }
    }
    return 0;
}

参考:

https://www.cnblogs.com/MyStringIsNotNull/p/9165675.html 这里有很多图可以参考 特别是左右旋

https://baike.baidu.com/item/Treap/4321536?fr=aladdin

模板 - FHQ - treap 无旋平衡树 整理的算法模板合集: ACM模板 #include<bits/stdc++.h> using namespace std; const int N = 100007; int n, m, tot, root; struct node{ int l, r; int key;//权值 int val;//平衡因子 int size;//子树个数 }tr[N]; void pushup(int p){ tr[p].size = tr[tr[p].l] 阅读详情

相关推荐

基于 VS Code + CMake + Make + GNU工具链 + OpenOCD 的通用MCU开发环境搭建教程

以CH32V307(RISCV)和STM32F103(Cortex-M3)为例的Vscode+gnu单片机环境搭建。

余十三_的博客 2173

平衡树——Treap (含完整模板)

平衡树——Treap基本概念:二叉搜索树(BST): 对于任意根节点,满足左儿子的权值<根节点的权值<右儿子的权值的二叉树。也就是说,BST的前序遍历的结果是从小到大的。通过BST,我们可以进行插入,删除元素等操作,还能记录一些信息查询更多东西。所有的操作都可以O(h)实现。h在最好的情况下是logn,但是在最坏情况下,BST可能会退化成链,复杂度极不稳定。那么能不能想办法使其平衡呢?于是就有了平

Lynstery's blog 3046

ESP32-CAM与Thonny的完美搭配:从烧录到通信的完整流程

本文详细介绍了如何将ESP32-CAM与Thonny IDE完美结合,从固件烧录到通信测试的完整流程。通过硬件连接、MicroPython固件烧录、Thonny环境配置以及摄像头功能开发等步骤,帮助开发者快速搭建高效的物联网开发环境,实现图像采集与无线通信功能。

tomato的博客 1122

平衡树(Treap模板)

平衡树(二叉搜索树+大根堆版)

北边一颗小星星 583

Linux下基于AHCI controller模块实现SATA Platform驱动附代码详细流程

本文主要是针对ARM A55集成了AHSATA controller模块开发sata驱动,通过Platform的形式在linux识别到SSD,本文详细讲述整个开发过程,同时对SATA Platform驱动进行讲解。1、配置SATA Phy的初始化;2、打开SATA Platform相关编译开关;3、配置设备树;4、linux启动识盘。

Luckiers的博客 2497

【机电杂谈2】BLDC和PMSM的特点和区别

在日常生活中,小到电动玩具,大到电动汽车,永磁电机的身影可以说是无处不在。有刷直流电机、无刷直流电机、永磁同步电机由于其结构和输出特定的不同也被应用到不同的场合。如果你经常拆一些玩具和家电,就会看到大量的有刷直流电机和无刷直流电机,而永磁同步电机主要应用在高精度的工业伺服和电动汽车领域。本文就从电机的结构和控制方面,对这几种常见的永磁电机做简单的梳理和归纳。

2934

普通平衡树(Treap模板题)

题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入数值x。 删除数值x(若有多个相同的数,应只删除一个)。 查询数值x的排名(若有多个相同的数,应输出最小的排名)。 查询排名为x的数值。 求数值x的前驱(前驱定义为小于x的最大的数)。 求数值x的后继(后继定义为大于x的最小的数)。 注意: 数据保证查询的结果一定存在。 输入格式 第一行为n,表示操作的个数。 接下来n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)。 输出

li_wen_zhuo的博客 704

cesium自定义指南针

项目需要一个指南针,用鼠标按住旋转指针,会让3d地图旋转,点击中心点重置方位。当然可以使用插件cesium-navigation-es6,但是样式不好修改,所以我自定义了一个指南针。

weixin_47017648的博客 750

普通平衡树【treap模板】

题目描述 链接 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入 xxx 数 删除 xxx 数 ( 若有多个相同的数,因只删除一个 ) 查询 xxx 数的排名 ( 排名定义为比当前数小的数的个数 +1+1+1 ) 查询排名为 xxx 的数 求 xxx 的前驱 ( 前驱定义为小于 xxx ,且最大的数 ) 求 xxx 的后继 ( 后继定义为大于 xxx ,且最小的数 ) 输入格式 第一行为 nnn ,表示操作的个数,下面 nnn 行每行有两个数 opt\text

m0_51864047的博客 241

RK3588开发笔记-麦克风阵列多pdm通道合并成一个声卡

在音频设备的开发中,特别是在多通道音频数据处理场景中,如何将多个PDM(Pulse Density Modulation)通道整合成一个声卡设备,是一个非常具有挑战性的问题。RK3588芯片作为一款性能强大的平台,提供了对多个音频通道的支持。本文将介绍如何在RK3588上将多个PDM通道合并成一个麦克风阵列声卡,从而在Linux系统下统一管理和使用,提高多通道音频的同步性。在本文中我们主要介绍使用2通道回采+4通道mic声音采集构成一个6通道声卡,加以回声消除实现一个多麦克风阵列。

flypig has a dream! 1924

Android AICore的核心组件工作原理解析

AICore通过LoRA实现个性化适配Gemini Nano提供多模态智能Safety Features保障可信运行,构建了端侧AI的完整生态。这种设计不仅让手机等移动设备能处理复杂AI任务(如实时多模态交互),还通过隐私保护机制打破了传统云端AI的数据依赖,为未来“设备即AI基础设施”的愿景奠定了基础。输入触发:用户输入“刚提交了代码,等审核”→ 进入TEE加密处理。Gemini Nano基础生成:通过原始权重W_q生成初始回复候选。LoRA个性化微调:通过A'和B'计算ΔW,更新W_q。

1551

算法模板——平衡树Treap 2

实现功能:同平衡树Treap 1(BZOJ3224 / tyvj1728) 这次的模板有了不少的改进,显然更加美观了,几乎每个部分都有了不少简化,尤其是删除部分,这个参照了hzwer神犇的写法,在此鸣谢,然后,贴模板走人 1 var 2 i,j,k,l,m,n,head,tot:longint; 3 a,b,lef,rig,fix:array[0..1...

125

C++和OpenGL实现3D游戏编程【连载7】——文字和汉字的显示(附源码)

上一节我们讨论了纹理在二维平面内不规则图形贴图的相关基础操作,本节我们开始了解游戏里文字以及汉字的显示方法。本节课我们将从基本的ASCII字符显示,拓展到中文字符的显示,最后再讲到纹理字符的显示,并对各种文字显示方法的优缺点和使用场景进行分析,这节课将使用到显示列表、兼容视图、屏幕图形转纹理等操作。

zhooyu的博客 1498

洛谷 P3369 【模板】普通平衡树 (Treap)

题目链接:P3369 【模板】普通平衡树 题意 构造一种数据结构满足给出的 6 种操作。 思路 平衡树 平衡树的模板题。 先学习了一下 Treap。 模板来自《算法竞赛进阶指南》。 代码 #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; const int inf = 0x3f3f...

G19850917的博客 339

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

带旋treap概念及模板,带例题:普通平衡树

数据结构要学吐了

977

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

[非旋平衡树]fhq_treap概念及模板,例题:普通平衡树,文艺线段树

非旋treap暴力地让人心动

882

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Treap模板 BZOJ 3224: Tyvj 1728 普通平衡树

Treap模板

unicornt的博客 341

平衡树treap模板

洛谷 P3369 【模板】普通平衡树(Treap/SBT) 1.插入x数 2.删除x数(若有多个相同的数,因只删除一个) 3.查询x数的排名(若有多个相同的数,因输出最小的排名) 4.查询排名为x的数 5.求x的前驱(前驱定义为小于x,且最大的数) 6.求x的后继(后继定义为大于x,且最小的数) 输入输出格式  输入格式: 第一行为n,表示操作的个数,下面n行每行有两个数opt和...

pcfbyssz的博客 291

P3369 【模板】普通平衡树(Treap/SBT)

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

weixin_30824277的博客 149

POJ 1442 平衡树Treap模板

点击打开链接 题意:输入m个数,询问n个数,第一个数如果是3,就输出在m的第三个数输入完成后第1大的数,第二个就输出第二大的数,但前提都是在输入完U[i]个数后 思路:用平衡树Treap进行插入和查询第K大的数,模版题 [html] view plain copy #include stdio.h>   #include string.h>

The_star_is_at的博客 496

算法模板——平衡树Treap

实现功能如下——1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) 本程序的实现原理为Treap平衡树 详见BZOJ3224 1 var 2 i,j,k,l,m,n,head,...

112

从零到一:Cosplay正片制作全流程与工具链解析

数字内容创作是当前多媒体领域的重要分支,其核心在于将创意想法通过系统化流程转化为高质量成品。在技术实现层面,需要掌握从前期规划到后期合成的完整工具链,包括角色设计、拍摄设备选型、图像处理等关键环节。RAW格式处理作为专业摄影的基础,能够保留更多图像信息,为后期调整提供更大空间;而图层管理则是复杂合成的核心技术,通过合理的分层和命名规范,确保特效合成的精准可控。这些技术不仅提升了创作效率,更在cosplay、影视制作、广告设计等场景中发挥着重要价值。本文以'颠魔二人组'的镜像疯狂cos制作为案例,详细解析如何

weixin_34185512的博客 300

[平衡树模板]Treap

算法标签 Treap 种下第一棵平衡树… 题目描述 Description 这是一道模板题。 如果觉得这个题水的可以做一下4544压行,是千古神犇花爸爸出的神犇题。 您需要写一种数据结构(可参考题目标题,但是这句话其实并没有什么用233),来维护一些数,其中需要提供以下操作: 1. 插入x数 2. 删除x数(若有多个相同的数,因只删除一个) 3. 查询x数的排名(若有多个相同的

DSL_HN_2002的博客 490

P3369 【模板】普通平衡树------平衡树Treap || FHQ_treap

原题 链接 #include<bits/stdc++.h> #define il inline #define ll long long #define RE register #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a...

weixin_44781226的博客 194

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

二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值。且左右子树也分别是二叉搜索树。(如下) $BST$的作用:维护一个有序数列,支持插入$x$,删除$x$,查询排名为$x$的数,查询$x$的排名,求$x$的前驱后继等操作。 时间复杂度:$O(操作数\times 树深度)$。 也就是插入一个有序序列时复杂度稳定在$O(N^...

baikeshe8603的博客 357

普通平衡树【模板】【treap】

学了一下treap的模板感觉还算容易理解。 其实就是平衡二叉树+堆 每个节点都有一个随机的权值。 根据堆的特性,只有右旋和左旋操作。 个人觉得关键代码就插入和删除部分涉及旋转的维护代码需要理解一下,其他的询问操作都很好写。 #pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; const int ma...

qq_39921637的博客 308
上一篇: 主席树 模板
explodee
博客等级 码龄9年 5粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值