luogu P3369 【模板】普通平衡树
————————————————
版权声明:本文为CSDN博主「ModestCoder_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ModestCoder_/article/details/90139481
清空一个节点
确定一个节点是父亲的左儿子还是右儿子
更新一个节点
把一个点连到另一点下面
上旋
splay
插入一个点
查询一个数的排名
查询排名为k的数
前驱、后继
删除一个点
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int sz, rt, f[maxn], key[maxn], size[maxn], recy[maxn], son[maxn][]; inline int read(){
int s = , w = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -;
for (; isdigit(c); c = getchar()) s = (s << ) + (s << ) + (c ^ );
return s * w;
} void clear(int x){
f[x] = key[x] = size[x] = recy[x] = son[x][] = son[x][] = ;
//5个数组全部清零
} int get(int x){
return son[f[x]][] == x;
//如果自己是父亲的右儿子,返回1;否则返回0(0为左儿子,1为右儿子)
} void update(int x){
if (x){//如果这个点存在
size[x] = recy[x];//自己重复的次数先累计
if (son[x][]) size[x] += size[son[x][]];
if (son[x][]) size[x] += size[son[x][]];
//如果存在儿子,把儿子的size累积到自己
//然后发现一个问题,更新自己的size时,必须保证儿子的size是正确的
//所以后面的操作,当牵扯到儿子和父亲时,应该先更新新儿子,后更新新父亲
}
} void connect(int x, int y, int z){//x连到y下面,关系为z
if (x) f[x] = y;//存在x,则x的父亲为y
if (y) son[y][z] = x;//存在y,y的z关系儿子为x
} void rotate(int x){//上旋x
int fa = f[x], ffa = f[fa], m = get(x), n = get(fa);//确定x,fa的关系
connect(son[x][m ^ ], fa, m);//把要转的儿子转到父亲下,关系为m
connect(fa, x, m ^ );//把父亲转到自己下面,关系为m^1
connect(x, ffa, n);//把自己转到父亲的父亲下,关系为n
update(fa), update(x);//先更新fa,再更新自己,可以自己想想为什么是这个顺序
} void splay(int x){
for (int fa; fa = f[x]; rotate(x))//每次总是旋转自己
if (f[fa]) rotate(get(x) == get(fa) ? fa : x);//如果有爷爷(父亲的父亲),看父亲与父亲的父亲的关系决定转哪个
rt = x;//别忘了,把根赋为当前点
} void insert(int x){
if (!rt){//树中没有一个节点
rt = ++sz;
key[rt] = x;
size[rt] = recy[rt] = ;
son[rt][] = son[rt][] = ;//赋初值
return;
}
int now = rt, fa = ;
while (){
if (key[now] == x){//树中已有此点,重复+1
++recy[now];
update(now); update(fa);
splay(now);//splay一下,保证平衡
return;
}
fa = now, now = son[now][x > key[now]];//满足二叉查找树的性质,往下跑
if (!now){
++sz;
key[sz] = x;
size[sz] = recy[sz] = ;//赋初值
f[sz] = fa;//父亲是fa
son[fa][x > key[fa]] = sz;//更新父亲的新儿子
update(fa);//更新父亲的size
splay(sz);//splay一下,保证平衡
return;
}
}
} int find(int x){//查排名
int now = rt, ans = ;
while (){
if (x < key[now]){
now = son[now][]; continue;//在左子树中
}
ans += size[son[now][]];//排名加上左子树节点个数
if (x == key[now]){ splay(now); return ans + ; }//值等于当前点,splay一下,保证平衡,排名+1为当前排名
ans += recy[now];//排名加上当前节点的数的个数
now = son[now][];//在右子树中
}
} int kth(int x){//查找排名为x的数
int now = rt;
while (){
if (son[now][] && x <= size[son[now][]]){//在左子树中
now = son[now][]; continue;
}
if (son[now][]) x -= size[son[now][]];//存在左儿子,排名减去左子树节点数
if (x <= recy[now]){ splay(now); return key[now]; }//说明就是当前点,splay一下,保证平衡,退出
x -= recy[now];//排名减去当前节点数的个数
now = son[now][];//在右子树中
}
} int pre(){//前驱为左子树中最大的那个
int now = son[rt][];
while (son[now][]) now = son[now][];
return now;
} int nxt(){//后继为右子树中最小的那个
int now = son[rt][];
while (son[now][]) now = son[now][];
return now;
} void del(int x){
int no_use = find(x);//find主要是把当前数的对应点找到,然后旋到根,返回值的排名在这里没用
if (recy[rt] > ){//情况1:有重复,重复-1,更新,退出
--recy[rt];
update(rt);
return;
}
//接下来都是没有重复的情况
if (!son[rt][] && !son[rt][]){//情况2:没有儿子,直接清空
clear(rt);
rt = ;
return;
}
if (!son[rt][]){//情况3:没有左儿子,只有右儿子,右儿子变成根,清除自己
int tmp = rt;
f[rt = son[rt][]] = ;
clear(tmp);
return;
}
if (!son[rt][]){//情况4:没有右儿子,只有左儿子,左儿子变成根,清除自己
int tmp = rt;
f[rt = son[rt][]] = ;
clear(tmp);
return;
}
//情况5:两个儿子都有,这是需要一个很简便的做法
//把前驱splay到根,保持左子树其他节点不用动
//原根右儿子变成前驱的右儿子
//原根功成身退,清除掉
//最后对前驱的size进行更新
int tmp = rt, left = pre();
splay(left);
connect(son[tmp][], rt, );
clear(tmp);
update(rt);
} int main(){
int M = read();
while (M--){
int opt = read(), x = read();
if (opt == ) insert(x);
if (opt == ) del(x);
if (opt == ) printf("%d\n", find(x));
if (opt == ) printf("%d\n", kth(x));
if (opt == ){
insert(x); printf("%d\n", key[pre()]); del(x);
}
if (opt == ){
insert(x); printf("%d\n", key[nxt()]); del(x);
}
}
return ;
}
luogu P3369 【模板】普通平衡树的更多相关文章
- [luogu P3369]【模板】普通平衡树(Treap/SBT)
[luogu P3369][模板]普通平衡树(Treap/SBT) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删 ...
- 数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) #include <cstdio> #define Max 100005 #define Inline _ ...
- 替罪羊树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 闲的没事,把各种平衡树都写写 比较比较... 下面是替罪羊树 #include <cstdio> #inc ...
- 红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 近几天闲来无事...就把各种平衡树都写了一下... 下面是红黑树(Red Black Tree) 喜闻乐见拿到了luo ...
- luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)
luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...
- [luogu P3384] [模板]树链剖分
[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...
- Luogu P2742 模板-二维凸包
Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...
- luoguP3391[模板]文艺平衡树(Splay) 题解
链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...
- luoguP3369[模板]普通平衡树(Treap/SBT) 题解
链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...
- 【luogu P3369 普通平衡树(Treap/SBT)】 模板 Splay
题目链接:https://www.luogu.org/problemnew/show/P3369 #include <cstdio> #include <algorithm> ...
随机推荐
- [Codeforces 1228E]Another Filling the Grid(组合数+容斥)
题目链接 解题思路: 容斥一下好久可以得到式子 \(\sum_{i=0}^{n}\sum_{j=0}^{n}(-1)^{i+j}C_n^iC_n^j(k-1)^{ni+nj-ij}k^{n^2-(ni ...
- C/C++画一个巨型五角星
把朱老师拉着画了半天 利用正弦定理判断一个点是否是否在五角星内,相对于五角星中心的四个象限特判一下来修改角度,把角度都转化成最上面的角,就差不多了,没仔细调整五角星位置,很丑 当然其实也有更方便的方法 ...
- SpringBoot安全篇Ⅵ --- 整合Spring Security
知识储备: 关于SpringSecurity的详细学习可以查看SpringSecurity的官方文档. Spring Security概览 应用程序的两个主要区域是"认证"和&qu ...
- 【存储类、链接、存储管理】分配内存:malloc()、free()
一.使用库函数:malloc()分配管理内存 (一)标识符(Identifier) 1. 定义变量时,使用了诸如 a.abc.mn123 这样的名字,它们都是程序员自己起的,一般能够表达出变量的作用, ...
- 编译出适合自己的nginx
上面是解压后的nginx源码 auto目录 上面的cc目录用于编译,lib库 os目录对系统进行判断,其他所有文件都是辅助conf脚本执行 判定nginx支持哪些模块,当前操作系统有哪些特性. CHA ...
- VUE 开发报表,非编码方式
官网:http://doc.sougn.com 下载地址:https://pan.baidu.com/share/init?surl=P0O9sjfzC8nuQxirDfjW1A 密码:4oev 先 ...
- VUE报表开发
因为在项目中经常开发一些报表,并且业务.逻辑其实都有大部分的重复部分. 所以将这些常用的模块抽象出来.并且可视化操作.封装成一款报表开发工具. 先看一下项目的一些效果:数据单项绑定 可视化操作: 数据 ...
- WeChall_Encodings: URL (Training, Encoding)
Your task is to decode the following: %59%69%70%70%65%68%21%20%59%6F%75%72%20%55%52%4C%20%69%73%20%6 ...
- 12-Java-myeclipse集成Tomcat步骤及Tomcat的使用步骤
一.了解Tomcat Tomcat是由Apache推出的一款免费开源的servlet容器/web应用服务器,可实现javaweb程序的装载,是配置JSP和java系统必备的一款环境 Tomcat目 ...
- JMeter之If Controller深究二
1.背景 接上文JMeter之If Controller深究一,在上文中提到压测采用的是JMeter3.1版本,本篇继续深究.基本确定问题原因后,宝路这边又做了不同版本的JMeter对比实验,这次加入 ...