平衡树·splay

2023-05-16

文章目录

    • 1.About splay
    • 2.基本操作
      • 2.1 数组是干啥的?
      • 2.2 基本操作
    • 3.splay
      • 3.1 rotate函数
      • 3.2 splay函数
    • 4.更新操作
      • 4.1 插入函数
      • 4.2 删除函数
    • 5.查询操作
      • 5.1 查询一个数的排名(rank函数)
      • 5.2 查询第k大(kth函数)
      • 5.3 查找一个数的前驱(lower)
      • 5.4 查找一个数的后继(upper)
    • 6. 模板题代码
    • 7. 写在最后

1.About splay

s p l a y splay splay是实现平衡树的一种方法
他需要满足一个条件,就是对于一个点为根节点的子树,他的左子树全部小于根节点,右子树全部大于根节点
那他为什么叫这个名字呢?
我们查询一下百度翻译
在这里插入图片描述
但是事实上,感觉 s p l a y splay splay跟张开没什么关系…

可以说成展开树吧

s p l a y splay splay的基本功能跟STL里面的 m u l t i s e t multiset multiset s e t set set)比较像

他的思想的优秀之处在于,他每次都把操作完\要操作的点旋转到根节点并且保证满足他的性质,这样可以便于操作

2.基本操作

2.1 数组是干啥的?

s p l a y splay splay中我们要用到一些数组
fa[x]表示x的爸爸是谁
son[x][2]表示x的儿子分别是谁,son[x][0]表示他的左儿子,son[x][1]表示他的右儿子,把他的儿子们存到一个数组里是为了旋转的时候比较方便,我们后面说
siz[x]表示以x为根节点的子树的大小
key[x]表示x点上存的值
recy[x]表示值为key[x]的数出现了几次(我们把它存在一个点上)
tot表示这颗 s p l a y splay splay里面有几个不同的权值
rt表示根节点的位置

2.2 基本操作

clear操作
这个操作和下面要说的删除函数erase连用,用于彻底清除一个点的所有权值(因为这个点后面继续往里加值得时候可能还会用到)

其实非常的简单,把所有数组都设成0就可以了

inline void clear(int x){
	fa[x]=son[x][0]=son[x][1]=siz[x]=key[x]=recy[x]=0;
}

locate操作
这个操作和下面的 s p l a y splay splay的精华splay函数和rotate函数连用,用于判断一个点是他爸爸的左儿子还是右儿子

判断方法很简单,就是判断他爸爸的右儿子是不是他自己就可以了

inline bool locate(int x){
	return son[fa[x]][1]==x;	
}

update操作
当我们进行旋转或者更新之后,原来的点之间的数量关系就有可能发生变化,这时候我们需要进行更新,让每个节点对应的siz值是对的

inline void update(int x){
	if(x){
		siz[x]=recy[x];
		if(son[x][0])siz[x]+=siz[son[x][0]];
		if(son[x][1])siz[x]+=siz[son[x][1]];
	}
}

注意if(x)不能省

3.splay

3.1 rotate函数

rotate(旋转),用来将一个点向我们想要的地方(向上)移一层

rotate分为左旋和右旋,下面以右旋为例

在这里插入图片描述
手画的好丑啊
我们想把X节点转到F的位置,我们不能单纯的把X转上去,因为这样会让X的度数变成4(G,L,R,F),不满足二叉树的性质了,所以我们必须要想一个办法。

我们发现,因为在左图中,R位于X的右子树,所以R应该比X大,所以当旋转完了之后,为了保证性质,所以R应该也在X的右子树,但是右子树已经被X曾经的爸爸给占了。但F的左子树不是还空着吗,就把R接到那里好了。

我们看左图,条件有L<X<R<F<B,在右图中,这个条件还是成立的!!!
也就是说,如果我们这样旋转,splay的性质并没有改变,所以左图和右图其实是等价的

所以这样旋转是合法的

当然左旋也差不多(可以想成F点从右图转到左图的过程)

当然,不要忘了update啊,X,F的关系都变了(特别是F原来是X的爸爸现在变成他儿子了),所以我们要update一下。

=========================
思想差不多就是那样,现在来简单说一下怎么把X旋上去

大家应该学过链表吧,我们在链表里想插入一个东西还挺麻烦的

这里的操作方法跟链表插入差不多,但是不同之处是所有点我们都知道他的编号,所以我们可以都存下来,然后就根本不用考虑顺序,瞎连就可以了

在这里插入图片描述
在这里插入图片描述

其中红线表示起点认终点为儿子,黑线表示终点认起点是爸爸

旋转完了之后的结果就是X之前的爸爸变成了自己的右儿子,自己之前都右儿子变成了自己的孙子,自己的爷爷变成了自己的爸爸,自己之前都兄弟变成了自己的孙子

inline void rotate(int x){
	int faz=fa[x],grand=fa[faz],side=locate(x);
	son[faz][side]=son[x][side^1],fa[son[faz][side]]=faz;//左右旋同时考虑
	son[x][side^1]=faz,fa[faz]=x;
	fa[x]=grand;
	if(grand)son[grand][son[grand][1]==faz]=x;//只有他有爷爷的时候才需要更新grand的儿子的情况
	update(faz),update(x);	//因为旋转后原来的faz跑到x下面了,所以要先更新faz
}

3.2 splay函数

我们学会了rotate,但是rotate只能向上转一层,我们要让他转到根节点,那怎么办呢?

我们用一个 s p l a y splay splay函数多次调用rotate来达到这一目的

但是我们需要分类讨论:
在这里插入图片描述
(声明洛谷版权)

为什么需要分类讨论呢?
我们看下面这张图可以更好的理解
在这里插入图片描述
在这里插入图片描述
我们发现,如果我们对于x,y,都是左(右)儿子的情况,如果我们连转两次x的话,那么我们发现X-Y-Z-B的链是始终存在的,这样的话就容易被卡掉

inline void splay(int x){
	for(int faz;faz=fa[x];rotate(x))
		if(fa[faz])
			rotate(locate(x)==locate(faz)?faz:x);
	rt=x;
}

4.更新操作

4.1 插入函数

插入其实非常好理解(但是码量不小)

思路是这个样子的

  1. 特判,如果树是空的就新加一个节点
  2. 从根节点往下扫,每次走向该走的节点(因为满足splay的性质,所以如果插入的数x<key[u]就往左走,如果大于就往右走)
  3. 如果遇到一个点key[u]=x,那么把那个点的计数器recy+1,更新自己,更新爸爸,把自己转到根节点(方便操作)
  4. 如果遇到一个点没有自己应该走的那个儿子,那就新加上一个点

看代码:

inline void insert(int x){
	if(!rt){//特判
		tot++;
		fa[tot]=son[tot][0]=son[tot][1]=0;
		siz[tot]=recy[tot]=1;
		key[tot]=x;
		rt=tot;
		return;
	}
	int u=rt,faz=0;
	while(1){
		if(key[u]==x){//如果有出现过的
			recy[u]++;
			update(u),update(faz);
			splay(u);
			return;
		}
		faz=u,u=son[u][x>key[u]];//选择走的方向
		if(!u){
			tot++;
			son[tot][0]=son[tot][1]=0;
			siz[tot]=recy[tot]=1;
			son[faz][x>key[faz]]=tot;
			fa[tot]=faz;
			key[tot]=x;
			update(faz);
			splay(tot);
			return;	
		}
	}
}

4.2 删除函数

查找函数
想要删除一个数,你要先找到他,所以删除的思路就是,先找到他,然后把它转到根节点,然后各种分类讨论(下面说)

怎么查找呢?跟插入差不多

如果x<key[u],就往左走
如果x>key[u],就往右走
如果x=key[u],就停下来

inline void find(int x){
	int u=rt;
	if(!u)return;
	while(son[u][x>key[u]]&&key[u]!=x)u=son[u][x>key[u]];
	splay(u);//记得转,要不然白找了
}

查找最大的小于根节点的数
这个其实很简单,因为他是满足性质的,所以那个数一定在根节点的左子树的右子树的右子树的右子树的右子树…

找最小的大于根节点的数其实同理

inline int pre(){
	int x=son[rt][0];
	while(son[x][1])x=son[x][1];
	return x;	
}

inline int next(){
	int x=son[rt][1];
	while(son[x][0])x=son[x][0];
	return x;	
}

删除

找到了之后我们就可以删了,删除要分五类情况讨论:

  1. 如果这个数出现了不止一次,即recy[rt]>1,则recy[rt]–,更新rt
  2. 如果这个数既没有左子树也没有右子树(整棵树只有一个点),则直接clear这个点,rt=0
  3. 如果这个数只有右子树,把根给自己的右儿子,清空原来的rt
  4. 如果这个数只有左子树,同理
  5. 我们找到最大的比要删除的数(根节点)大的数,把他转到根节点,这个时候我们要删的点就到根节点的右儿子的位置上了,连接一下根节点和要删除的点的右儿子就可以了
inline void erase(int x){
	rank(x);
	if(recy[rt]>1){
		recy[rt]--;
		update(rt);
		return;	
	}
	if(!son[rt][0]&&!son[rt][1]){
		clear(rt);
		rt=0;
		return;	
	}
	if(!son[rt][0]){
		int old=rt;
		rt=son[rt][1];
		fa[rt]=0;
		clear(old);
		return;
	}
	if(!son[rt][1]){
		int old=rt;
		rt=son[rt][0];
		fa[rt]=0;
		clear(old);
		return;	
	}
	int old=rt,lft=pre();
	splay(lft);
	son[rt][1]=son[old][1];
	fa[son[old][1]]=rt;
	clear(old);
	update(rt);
}

5.查询操作

5.1 查询一个数的排名(rank函数)

这个操作其实也不难,我们从根节点往下扫,开一个计数器res

如果x<key[u],往左儿子走
否则将计数器加上siz[左儿子](因为他左儿子的数肯定都比他小)
当遇到一个点他的key等于x,返回res+1
如果不相等,计数器加上recy[u],往右儿子走

inline int rank(int x){
	int u=rt,res=0;
	while(1){
		if(x<key[u])u=son[u][0];
		else{
			res+=siz[son[u][0]];
			if(x==key[u]){
				splay(u);//可以不转,但是转了的话后面可以省事(不用写find)
				return res+1;
			}
			res+=recy[u];
			u=son[u][1];
		}
	}
}

5.2 查询第k大(kth函数)

这个跟上一个其实差不多

如果有左儿子并且k没有左儿子的数量多,往左儿子走
否则
计算一下如果第k大是当前节点的话k最多是多少(左儿子大小+当前节点recy),如果k小于那个值,返回当前节点的值
如果不小于,k减去那个值,往右儿子走

inline int kth(int x){
	int u=rt;
	while(1){
		if(son[u][0]&&x<=siz[son[u][0]])u=son[u][0];
		else{
			int sum=siz[son[u][0]]+recy[u];
			if(x<=sum)return key[u];
			u=son[u][1];
			x-=sum;	
		}
	}
}

5.3 查找一个数的前驱(lower)

怎么做呢?其实很简单,首先把那个数插进去,跑一下4.2里面说到的最大的小于根节点的数,就是他的前驱,然后再删掉那个点就可以了

inline int lower(int x){
	insert(x);
	int res=key[pre()];
	erase(x);
	return res;	
}

5.4 查找一个数的后继(upper)

跟5.3差不多,也是先插进去,调用next()函数,然后再删掉

inline int upper(int x){
	insert(x);
	int res=key[next()];
	erase(x);
	return res;	
}

6. 模板题代码

# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
# include <stack>
# include <vector>
# include <set>
# include <map>
# include <cstdlib>
# include <ctime>
using namespace std;

# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)

typedef long long ll;
const int N=1e5+5;
const int inf=0x7fffffff;
const double eps=1e-7;
template <typename T> void read(T &x){
	x=0;int f=1;
	char c=getchar();
	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
	for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
	x*=f;
}

int n;
int fa[N],son[N][2],siz[N],key[N],recy[N];
int rt,tot;

inline void clear(int x){
	fa[x]=son[x][0]=son[x][1]=siz[x]=key[x]=recy[x]=0;
}

inline bool locate(int x){
	return son[fa[x]][1]==x;	
}

inline void update(int x){
	if(x){
		siz[x]=recy[x];
		if(son[x][0])siz[x]+=siz[son[x][0]];
		if(son[x][1])siz[x]+=siz[son[x][1]];
	}
}

inline void rotate(int x){
	int faz=fa[x],grand=fa[faz],side=locate(x);
	son[faz][side]=son[x][side^1],fa[son[faz][side]]=faz;
	son[x][side^1]=faz,fa[faz]=x;
	fa[x]=grand;
	if(grand)son[grand][son[grand][1]==faz]=x;
	update(faz),update(x);	
}

inline void splay(int x){
	for(int faz;faz=fa[x];rotate(x))
		if(fa[faz])
			rotate(locate(x)==locate(faz)?faz:x);
	rt=x;
}

inline int pre(){
	int x=son[rt][0];
	while(son[x][1])x=son[x][1];
	return x;	
}

inline int next(){
	int x=son[rt][1];
	while(son[x][0])x=son[x][0];
	return x;	
}

inline int rank(int x){
	int u=rt,res=0;
	while(1){
		if(x<key[u])u=son[u][0];
		else{
			res+=siz[son[u][0]];
			if(x==key[u]){
				splay(u);
				return res+1;
			}
			res+=recy[u];
			u=son[u][1];
		}
	}
}

inline int kth(int x){
	int u=rt;
	while(1){
		if(son[u][0]&&x<=siz[son[u][0]])u=son[u][0];
		else{
			int sum=siz[son[u][0]]+recy[u];
			if(x<=sum)return key[u];
			u=son[u][1];
			x-=sum;	
		}
	}
}

inline void insert(int x){
	if(!rt){
		tot++;
		fa[tot]=son[tot][0]=son[tot][1]=0;
		siz[tot]=recy[tot]=1;
		key[tot]=x;
		rt=tot;
		return;
	}
	int u=rt,faz=0;
	while(1){
		if(key[u]==x){
			recy[u]++;
			update(u),update(faz);
			splay(u);
			return;
		}
		faz=u,u=son[u][x>key[u]];
		if(!u){
			tot++;
			son[tot][0]=son[tot][1]=0;
			siz[tot]=recy[tot]=1;
			son[faz][x>key[faz]]=tot;
			fa[tot]=faz;
			key[tot]=x;
			update(faz);
			splay(tot);
			return;	
		}
	}
}

inline void erase(int x){
	rank(x);//这里偷了个懒,因为rank后面我们把那个点转上去了,所以我们这里就不用再专门的写find了
	if(recy[rt]>1){
		recy[rt]--;
		update(rt);
		return;	
	}
	if(!son[rt][0]&&!son[rt][1]){
		clear(rt);
		rt=0;
		return;	
	}
	if(!son[rt][0]){
		int old=rt;
		rt=son[rt][1];
		fa[rt]=0;
		clear(old);
		return;
	}
	if(!son[rt][1]){
		int old=rt;
		rt=son[rt][0];
		fa[rt]=0;
		clear(old);
		return;	
	}
	int old=rt,lft=pre();
	splay(lft);
	son[rt][1]=son[old][1];
	fa[son[old][1]]=rt;
	clear(old);
	update(rt);
}	

inline int lower(int x){
	insert(x);
	int res=key[pre()];
	erase(x);
	return res;	
}

inline int upper(int x){
	insert(x);
	int res=key[next()];
	erase(x);
	return res;	
}

int main()
{
	read(n);
	Rep(i,1,n){
		int opt,x;
		read(opt),read(x);
		switch(opt){
			case 1:insert(x);break;
			case 2:erase(x);break;
			case 3:printf("%d\n",rank(x));break;
			case 4:printf("%d\n",kth(x));break;
			case 5:printf("%d\n",lower(x));break;
			case 6:printf("%d\n",upper(x));break;
		}
	}
	return 0;
}

7. 写在最后

总算是写完了

s p l a y splay splay作为码量最大的平衡树之一以及效率最低的平衡树之一,至少不用像 t r e a p treap treap一样靠脸吃饭吧…

by:一位只会splay的蒟蒻

素材来源: l u o g u luogu luogu博客, y y b yyb yyb的博客( o r z y y b orzyyb orzyyb)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

平衡树·splay 的相关文章

  • 利用冒泡法对10个数字进行排序

    将10个数由小到大进行排序 用冒泡法 第一趟比较 xff0c 如果是6个元素 xff0c 要进行n 1 xff0c 也就是6 1等于5次两两比较 第二趟比较中 xff0c 要进行n j xff08 j是趟数 xff09 两两比较 xff0c
  • Cloudreve添加腾讯云对象存储策略教程

    Cloudreve安装好后就可以添加存储策略了 xff0c 设置文件存储的位置 xff0c 我将文件存储在腾讯云对象存储 xff0c 使用内容分发进行下载加速和保护源站 对象存储和内容分发是收费的 xff0c 需要购买存储容量包 内容分发流
  • 汇编语言指令大全

    一 数据传输指令 它们在存贮器和寄存器 寄存器和输入输出端口之间传送数据 1 通用数据传送指令 MOV 传送字或字节 MOVSX 先符号扩展 再传送 MOVZX 先零扩展 再传送 PUSH 把字压入堆栈 POP 把字弹出堆栈 PUSHA 把
  • Access-Control-Allow-Origin跨域解决及详细介绍

    首先 xff0c 跨域不是问题 是一种安全机制 这是你在开发时 上线前就必须提前考虑到的安全问题并且采取合适的手段去避免这个问题带来的程序错误 不过通常情况下 xff0c 前端开发的小伙伴们都非常坚信后端小伙伴的接口一定已经处理好了跨域这个
  • CCF-CSP历年真题大全附题解(202303已更)

    CCF CSP真题拿来练手 xff0c 持续更新 xff0c CCF CSP真题拿来练手 xff0c 如果对自己没有拿高分的期望的话 xff0c 可以就琢磨着写一二三题就好 xff0c 三题和四题可以稍微瞧一瞧 xff0c 可以就拿最基础的
  • Notepad ++ 安装与配置

    目录 Notepad 43 43 获取与安装 Notepad 43 43 是什么 获取 Notepad 43 43 安装包 安装 Notepad 43 43 可以很方便的转换编码 配置 Notepad 43 43 首选项 常用 编辑 暗黑模
  • 在Docker中安装并修改MySQL中的 my.cnf 配置文件

    前言 前期经过MySQL主从复制之后 xff0c 发现数据库的读写非常慢 xff0c 而且经常发生MySQL连接数过小 xff0c 导致整个数据库崩溃的情况 通过修改MySQL中的 my cnf 配置文件参数 xff0c 以达到MySQL关
  • Armbian 笔记一_初次登陆配置 Armbian 系统

    目录 初次登陆配置 arm 系统 参考链接和当前场景 初次登陆配置 root 密码 默认终端 普通用户 无线网络 时间和地区设置 关闭系统 初次登陆配置 arm 系统 参考链接和当前场景 参考燃吹哥哥的这篇博客 真的炒鸡详细 xff1a 猿
  • Armbian 笔记五_如何在 Armbian 上安装 xfce4 桌面

    目录 使用 armbian software 选择 Desktop 安装 xfce4 桌面 准备工作 正常开机 必须存在着一个普通用户 连接有线网络 下载安装设置 armbian software 201 是 Desktop 输入普通用户
  • 二维数组中的查找(杨氏矩阵(C语言+Java))

    二维数组中的查找这道题 xff0c 出自 剑指Offer 也是著名的杨氏矩阵 在一个 n m 的二维数组中 xff0c 每一行都按照从左到右递增的顺序排序 xff0c 每一列都按照从上到下递增的 输入一个数 xff0c 判断矩阵中是否存在这
  • 【操作系统实验】Ubuntu Linux 虚拟机目录文件操作

    文章目录 目录的创建和删除创建目录删除目录 文件的创建和删除创建文件删除文件 复制目录 文件移动目录 文件 目录的创建和删除 创建目录 mkdir 命令 功能描述 xff1a mkdir命令用来创建指定名称的目录 要求创建目录的用户在当前目
  • mysql-8.0.30最新密码重置方法,看这一篇就够了

    博主自己多次忘记自己本地MySQL的密码 xff0c 多次 删库跑路 xff0c 现写下这篇技术贴 xff0c 一来是为后续网友们遇到相同问题可以少走弯路 xff0c 二来是给自己做一个备忘录 之前查阅了很多关于更改MySQL密码的方式是在
  • Centos7安装OpenStack Rocky版本和openstack基本使用

    文章目录 环境 xff1a 设置主机名验证配置域名和IP映射关闭防火墙和SeLinux时间同步配置OpenStack rocky的yum源文件安装centos release openstack rocky安装openstack客户端安装数
  • 详解%d、%%d、%%%d和\\%d的区别

    1 d xff0c 表示按整型输出后面给出的变量的值 2 d xff0c 这就会被拆成两部分看待 xff0c 一是 在C语言中就是输出一个 xff0c 而是 d 就是一个普通字符 xff0c 所以当 d 在一起时 xff0c 其含义就是输出
  • C语言数组小记1

    在一维数值里 xff1a xff08 假设a 0 的地址为2000 xff09 如 xff1a int a 61 10 9 8 7 6 5 xff1b printf xff08 d d d xff0c a xff0c a 0 xff0c a
  • C语言数组小记2

    示例 xff1a 在二维数组下行与列的问题 如 xff1a int a 3 3 61 9 8 7 6 5 4 3 2 1 假设我们a 0 0 的地址是2000 xff0c a 0 1 的地址是2004 xff0c 相差4个字节 printf
  • 正点stm32串口中断理解

    首先把程序放上来 xff0c 最后结论总结在最后 u8 USART RX BUF USART REC LEN u16 USART RX STA 61 0 void USART1 IRQHandler void 串口1中断服务程序 u8 Re
  • windows用xrdp方式远程桌面连接ubuntu

    windows系统 xff1a win10 ubuntu系统 xff1a 18 04 5 参考文章 xff1a https forum ubuntu org cn viewtopic php f 61 54 amp p 61 3221658
  • Linux中用vim编辑器打开时自动补入头文件,注释方法

    1 首先我用的是乌班头的linux xff0c 打开终端 2 通常我们打开终端的时候是直接在home目录下3 我们直接直接退到根目录下 xff0c 找到etc目录 4 输入sudo vi etc vim vimrc 其实熟练的也可以234步
  • HTTP中get、post、put、delete的区别

    今天开发遇到了 put请求 xff0c 顺便过来拔拔草 xff01 先说说最常用的get请求跟post请求的区别 xff1a GET请求 xff1a 一般是获取服务器资源 xff1b get请求的查询参数需要挂载请求地址中 xff1b 请求

随机推荐

  • ubuntu网络无法连接(桥接模式)

    ubuntu桥接模式网络无法连接 问题描述 问题描述 最近几天遇到了一个网络配置问题 xff0c 因为之前的虚拟机崩了 xff0c 我就跟换了ubuntu21 04版本 xff0c 创建虚拟机的时候就选了桥接模式 xff0c 虚拟网络编辑器
  • centos7安装Prometheus+Grafana步骤

    sentos7安装Prometheus 43 Grafana 环境部署规划表 服务端 监视器 Prometheus服务端 Grafana服务端CentOS 7 9grafana192 168 3 230客户端 被监控主机 CentOS 7
  • gitlab-ce安装

    gitlab ce安装 sentos 下载 wget http mirrors tuna tsinghua edu cn gitlab ce yum el7 gitlab ce 12 9 0 ce 0 el7 x86 64 rpm 2021
  • gitlab-runner升级

    gitlab runner版本升级 添加GitLab官方仓库 For Debian Ubuntu Mint curl L https packages gitlab com install repositories runner gitla
  • docker可视化工具Shipyard

    Docker Shipyard Shipyard简介 shipyard是一个开源的docker管理平台 xff0c 其特性主要包括 xff1a 支持节点动态集群 xff0c 可扩展节点的规模 xff08 swarm etcd方案 xff09
  • jira8安装

    Jira8 3 3安装 下载jira安装包 xff0c 破解包和jdk包 链接 xff1a https pan baidu com s 1yHsXkW1ZpkcNQeBkvE Hog 提取码 xff1a zzzz 安装数据库 网上很多就不在
  • goteleport10.0本地安装使用

    goteleport10 0本地安装使用 环境说明 master xff1a 192 168 8 132 node1 xff1a 192 168 8 131 node2 xff1a 192 168 8 133 master本地生成域名证书
  • [csp2019]Emiya家今天的饭

    作为提高组 d 2 t 1 d2t1 d 2 t 1 xff0c 比去年难 所以这道题我打的特别的差 32pts 这道题我们很显然可以看到可以打一个暴力 复杂度
  • React 函数组件导出自定义方法的办法说明

    在进行React开发时 xff0c 函数组件是比较方便的 xff0c 由于函数组件没有this指针 xff0c 因此如果想在父组件里调用函数型子组件的方法 xff0c 就需要用到React useImperativeHandle 这个帮助函
  • centos7防火墙关闭telnet端口不通

    root 64 zabbix agen2 systemctl status firewalld firewalld service firewalld dynamic firewall daemon Loaded loaded usr li
  • centos7安装配置夜莺V5+睿象云实现电话短信告警

    服务器清单 hostnameipmaster192 168 8 128zabbix agen1192 168 8 134 master安装夜莺依赖 install prometheus mkdir p opt prometheus wget
  • (踩坑指南)cd .ssh返回-bash: cd: .ssh:No such file or directory怎么办

    1 cd ssh返回 bash cd ssh No such file or directory怎么办 出现如下界面 有时候没必要在细节上过于拘泥 xff0c 不如直接配置秘钥 xff0c 反而一切都妥妥的了 2 如何保存退出 xff1f
  • Python数据处理工具—去除TXT文件里面相同的数据

    前言 本次分享的是一个对TXT数据进行处理的一个小工具 xff0c 功能如题 xff0c 是把TXT里面相同的数据给清洗掉是剩下唯一的一个 一 数据 随便在文件里面写了一点数据 xff0c 可以看到里面有很多重复的数据 xff0c 那么里面
  • Python进行ffmpeg推流和拉流rtsp、rtmp

    流媒体协议 xff0c 英文学名Streaming Protocol xff0c 用一句人话来解释 xff1a 流媒体协议是一种用于通过 Web 传递多媒体的协议 传统视频流协议 xff1a RTMP和RTSP xff0c 其中 RTMP
  • ROS Python 入门学习笔记--1--工作空间与功能包的创建

    上一节我们已经成功安装了ROS xff0c 并且还进行了小海龟实验的一个初步探索 xff0c 这一节主要给大家介绍一下ROS工作空间与功能包的创建 先来聊一下ROS的文件结构 xff1a 图片来源 xff1a 中国大学MOOC 在ROS当中
  • python运算符&用法的详细介绍

    目录 1 算数运算 2 比较运算符 3 成员运算符 4 逻辑运算 5 赋值运算 附 xff1a 类型转换 1 算数运算 运算符 xff1a 43 加 减 乘 除 整除 余数 幂运算 多用于整数 浮点数进行计算 43 也可用于字符串 xff0
  • 第三篇 树莓派的串口通信和语音识别模块

    目录 一 串口 xff08 UART xff09 二 wiringPi提供的串口API 三 语音识别模块 1 阅读模块代码 代码阅读工具 xff1a Souces Insight4 0安装 激活 汉化等 语音识别 xff08 口令模式 xf
  • 安装配置 JupyterLab ubuntu20.04

    目录 编辑 xff08 1 xff09 安装 xff08 2 xff09 配置 xff08 1 xff09 生成配置文件 xff08 2 xff09 生成jupyterlab的登录密码 xff08 3 xff09 修改 jupyter 的配
  • 笔记本安装双系统(win11+centos7)自己遇到坑的总结

    笔记本安装CentOS操作系统 当初在学习CentOS7的时候 就想在自己的笔记本上装一个CentOS7 装CentOS7和Windows双系统 xff0c 安装的过程中也查阅很多资料但是都不是很齐全 xff0c 我将自己安装的全过程总结出
  • 平衡树·splay

    文章目录 1 About splay2 基本操作2 1 数组是干啥的 xff1f 2 2 基本操作 3 splay3 1 rotate函数3 2 splay函数 4 更新操作4 1 插入函数4 2 删除函数 5 查询操作5 1 查询一个数的