首页 > 其他分享 >平衡树

平衡树

时间:2024-04-21 18:11:35浏览次数:15  
标签:int tr t2 t1 merge 平衡 root

由于我们学过数据结构,在二叉搜索树中,如果给出的数据是一条链的话,那么每次查询等操作都是O(n)的级别,所以为了优化搜索查找修改的效率,需要创建平衡树,来达到logn级别的查询和修改

对于一颗二叉搜索树,我们可以将它进行分裂操作,假如我们要进行查询一个数 $u$ 那么我们就可以分裂这棵树,把他分成两颗树,由于二叉树的性质,我们肯定能够把左边的树分成 $<= u$ 右边的树都是 $>u$ 的两颗树有了这两棵树,我们就可以进行查询,由于分裂之后二叉搜索树的性质不变,就可以做到查询操作了,不过由于我们分裂了,所以分裂之后不要忘记合并就是了

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
struct node{
    int l,r,key,sz,val;//左子树,右子树,关键值,树的大小,以及树中存的值
}tr[N];
int t1,t2,t3,ck,root;//t1是分裂之后左子树的根节点,t2是右子树的根节点
//t3是 x=v 的根节点,ck就是一个节点计数器,root是树的根
mt19937 sj(1141514); //随机数,我们将树的尽量分成大根堆的形式,key即为值
//由于正态分布的原因,所以我们创建出来的树可以压到log的高度
int xj(int x){
    tr[++ck]={0,0,(int)sj(),1,x};
    return ck;
}
void pushup(int u){
    tr[u].sz=tr[tr[u].l].sz+tr[tr[u].r].sz+1;
}
void split(int u,int v,int &x,int &y){
    if(!u) return x=y=0,void();
    if(tr[u].val>v) y=u,split(tr[u].l,v,x,tr[u].l);//若节点大于查询值,向左分裂
    else x=u,split(tr[u].r,v,tr[u].r,y);
    pushup(u);
}
int merge(int x,int y){
    if(!x||!y) return x+y;
    if(tr[x].key>tr[y].key){//大根堆性质合并 
        tr[x].r=merge(tr[x].r,y);
        pushup(x);
        return x;
    }
    else{
        tr[y].l=merge(x,tr[y].l);
        pushup(y);
        return y;
    }
}
void insert(int x){
    split(root,x,t1,t2);
    root=merge(merge(t1,xj(x)),t2);
}
void erase(int x){
    split(root,x,t1,t2); //先根据x分成两半
    split(t1,x-1,t1,t3);//在从<=x的树上继续分成两半,此时分成 <=x-1, >x-1
    t3=merge(tr[t3].l,tr[t3].r);//t3即为 >x-1的根节点,所以我们直接合并左右子树即可
    //不加入根节点,因为此时根节点一定是 =x
    root=merge(merge(t1,t3),t2);//怎么分的树怎么合  
}
int find(int x){
    split(root,x-1,t1,t2);
    int res=tr[t1].sz+1;
    root=merge(t1,t2);
    return res;
}
int kth(int x){
    int u=root;
    while(u){
        int tmp=tr[tr[u].l].sz+1; //左子树的值全部比当前节点小
        if(tmp==x) break;
        else if(tmp>x) u=tr[u].l;
        else x-=tmp,u=tr[u].r;  
    }
    return tr[u].val;
}
int find_pre(int x){
    split(root,x-1,t1,t2);
    int u=t1;
    while(tr[u].r) u=tr[u].r;
    root=merge(t1,t2);
    return tr[u].val;
}
int find_next(int x){
    split(root,x,t1,t2);
    int u=t2;
    while(tr[u].l) u=tr[u].l;
    root=merge(t1,t2);
    return tr[u].val;
}
signed main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int n,m; cin>>n>>m;
    for(int i=1;i<=n;i++){
        int x; cin>>x;
        insert(x);
    }
    int lst=0,res=0;
    while(m--){
        int op,x; cin>>op>>x;
        x^=lst;
        if(op==1) insert(x);
        else if(op==2) erase(x);
        else if(op==3) lst=find(x),res^=lst;
        else if(op==4) lst=kth(x),res^=lst;
        else if(op==5) lst=find_pre(x),res^=lst;
        else lst=find_next(x),res^=lst;
    }
    cout<<res;
    return 0;
}

 

标签:int,tr,t2,t1,merge,平衡,root
From: https://www.cnblogs.com/o-Sakurajimamai-o/p/18149278

相关文章

  • 技术周刊的转变:如何平衡热爱与现实?
    大家好,我是那个自己打脸自己的猫哥,本来说周刊不做订阅制的,现在却推出了订阅专栏。今天想为自己辩护一下,同时聊聊技术周刊今后的发展计划。首先回顾一下我过去的想法吧,然后再解释为什么会突然出现转变。出于对Python的热爱以及对国外几个Python周刊的效仿,我从一年前开始连载......
  • redis为什么一定要用跳表实现有序集合,却不用平衡树,红黑树或者B+树呢?
    平衡树vs跳表平衡树必须满足所有节点的左右子树高度差不超过1,也就是平衡因子范围为[-1,1]。但是对于范围查询来说,利用平衡树通过中序遍历达到和跳表一样的效果,但是平衡树的每一次插入或者删除操作都需要保证整棵树的绝对平衡,只要不平衡就会通过旋转的方式来重新保持平衡,这个过......
  • P1337 [JSOI2004] 平衡点 / 吊打XXX
    原题链接题解朝合力方向位移一段距离,并逐渐减小这个位移距离,需要痛苦的调参code#include<bits/stdc++.h>usingnamespacestd;doublex=0,y=0;structnode{doublex,y,w;}pos[1005];intn;voidmoves(doublelen){doublefx=0,fy=0;for(inti=1;i<=n;i......
  • 关于pwn题的栈平衡中ret的作用
    以nssctf里的where_is_my_shell为例题目提供了一个system函数,和一个buf数组。数组的栈空间如图所示,这里不讨论怎么解题,只说明payload里的ret的作用。假设没有ret,栈溢出到ret的时候内容如下:第一个八字节:(图示位置)存储poprdi;ret;的地址它下面的八个字节存储要pop的参数。......
  • 红黑树的平衡之道:深入解析右旋操作的原理与实践
    红黑树的平衡之道:深入解析右旋操作的原理与实践一、红黑树旋转的背景二、右旋(RIGHT-ROTATE)的原理三、右旋(RIGHT-ROTATE)的算法步骤四、右旋(RIGHT-ROTATE)的伪代码五、右旋(RIGHT-ROTATE)的C代码实现五、结论红黑树作为一种高效的平衡搜索树,其插入和删除操作的时间复杂度......
  • 17天【代码随想录算法训练营34期】第六章 二叉树part04(● 110.平衡二叉树 ● 257.
    110.平衡二叉树#Definitionforabinarytreenode.#classTreeNode:#def__init__(self,val=0,left=None,right=None):#self.val=val#self.left=left#self.right=rightclassSolution:defgetDepth(self,root):......
  • 数据结构:二叉搜索树、平衡二叉树(AVL树)、红黑树、B树、B+树
    个人理解浅谈数据结构,应对八股文面试目录前言一、二叉搜索树(二叉排序树、二叉查找树、AVL树)(1)二叉树的特点:(2)二叉树的优缺点二、平衡二叉树(高度平衡树,最早的自平衡二叉树)(1)平衡二叉树的特点:(2)平衡二叉树的优缺点三、红黑树(1)红黑树的特点(2)红黑树的优缺点四、红黑树......
  • 可视化红黑树详解(gif图演示,洛谷P3369 普通平衡树)
    写在前面推荐一个很实用的工具:红黑树可视化本文参考OIwiki中的红黑树代码,读者也可以参考该篇解析(写得还是很不错的),不过OIWiki里删除后平衡维护的Case4和Case5在代码细节上稍微有些问题(把c......
  • 数据结构之二叉树和平衡二叉树
    1、二叉树:packagecom.datastructure.tree;//一个常用的第三方库是ApacheCommonsCollections,它提供了一个名为BinaryTree的类,用于表示二叉树。//可以使用org.apache.commons.collections4.BinaryTree类创建二叉树和进行操作。//可以在Maven中添加以下依赖项://<dependenc......
  • 故障诊断模型 | 基于多信号融合和改进的深度卷积生成对抗网络的不平衡数据故障诊断方
    文章目录文章概述模型描述参考资料文章概述本文提出了一种解决数据不平衡问题并提高诊断准确性的诊断方法。首先,通过小波变换处理来自多个传感器的信号,以增强数据特征,然后通过池化和拼接操作对其进行压缩和融合。随后,构建改进的对抗网络来生成新的样本进......