Template -「平衡树」
Fhq-Treap.
// Fhq-Treap
const int MAXN = 1e5 + 5;
struct Fhq_Treap {
#define Lson Tr[p].l
#define Rson Tr[p].r
struct Fhq_Node {
int l, r, Val, Key, Size;
Fhq_Node () {}
Fhq_Node (int L, int R, int V, int K, int S) {
l = L, r = R, Val = V, Key = K, Size = S;
}
} Tr[MAXN];
int Tot, Root;
Fhq_Treap () { Tot = 0, Root = 0; }
int Get(int Val) {
Tr[++Tot] = Fhq_Node (0, 0, Val, rand(), 1);
return Tot;
}
void Pull (int p) { Tr[p].Size = Tr[Lson].Size + Tr[Rson].Size + 1; }
void Split (int p, int Val, int &x, int &y) {
if (!p) {
x = 0, y = 0;
return;
}
if (Tr[p].Val <= Val)
x = p, Split (Rson, Val, Rson, y);
else
y = p, Split (Lson, Val, x, Lson);
Pull (p);
}
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), Pull (x);
return x;
}
else {
Tr[y].l = Merge (x, Tr[y].l), Pull (y);
return y;
}
}
void Insert (int Val) {
int x, y;
Split (Root, Val, x, y), Root = Merge (Merge (x, Get(Val)), y);
}
void Delete (int Val) {
int x, y, z;
Split (Root, Val, x, z), Split (x, Val - 1, x, y);
y = Merge (Tr[y].l, Tr[y].r), Root = Merge (Merge (x, y), z);
}
int Get_Rank (int Val) {
int x, y, Ret;
Split (Root, Val - 1, x, y);
Ret = Tr[x].Size + 1, Root = Merge (x, y);
return Ret;
}
int Get_Val (int Rank) {
int p = Root;
while (p) {
if (Tr[Lson].Size + 1 == Rank)
return Tr[p].Val;
else if (Rank <= Tr[Lson].Size)
p = Lson;
else
Rank -= (Tr[Lson].Size + 1), p = Rson;
}
return 0;
}
int Get_Pre (int Val) {
int x, y, p;
Split (Root, Val - 1, x, y), p = x;
while (Rson)
p = Rson;
int ret = Tr[p].Val;
Root = Merge (x, y);
return ret;
}
int Get_Next (int Val) {
int x, y, p;
Split (Root, Val, x, y), p = y;
while (Lson)
p = Lson;
int ret = Tr[p].Val;
Root = Merge (x, y);
return ret;
}
#undef Lson
#undef Rson
} Tree;
Splay.
struct Splay_Tree {
#define Lson Tr[p].Son[0]
#define Rson Tr[p].Son[1]
#define Inf 0x3f3f3f3f
struct Splay_Node {
int Son[2], Val, Cnt, Size, Fa;
Splay_Node () {}
Splay_Node (int V, int C, int S, int F) {
Val = V, Cnt = C, Size = S, Fa = F;
}
} Tr[MAXN];
int Tot, Root;
bool Ident (int p) { return Tr[Tr[p].Fa].Son[1] == p; }
int Get (int Val, int Fa) {
Tr[++Tot].Fa = Fa, Tr[Tot].Cnt = Tr[Tot].Size = 1, Tr[Tot].Val = Val;
return Tot;
}
void Pull (int p) { Tr[p].Size = Tr[Lson].Size + Tr[Rson].Size + Tr[p].Cnt; }
void Build () {
Root = Get (-Inf, 0);
Tr[Root].Son[1] = Get (Inf, Root), Pull (Root);
}
void Connect (int p, int Fa, int flag) { Tr[Fa].Son[flag] = p, Tr[p].Fa = Fa; }
void Rotate (int p) {
int Fa = Tr[p].Fa, Grand = Tr[Fa].Fa;
int Flag1 = Ident (p), Flag2 = Ident (Fa);
Connect (p, Grand, Flag2), Connect (Tr[p].Son[Flag1 ^ 1], Fa, Flag1);
Connect (Fa, p, Flag1 ^ 1), Pull (Fa), Pull (p);
}
void Splay (int p, int To) {
for (int Fa = Tr[p].Fa; Tr[p].Fa != To; Rotate (p), Fa = Tr[p].Fa)
if (Tr[Fa].Fa != To)
Ident (p) == Ident (Fa) ? Rotate (Fa) : Rotate (p);
if (!To)
Root = p;
}
int Find (int p, int Val) {
if (!p)
return 0;
if (Val == Tr[p].Val)
return p;
else if (Val < Tr[p].Val)
return Find (Lson, Val);
return Find (Rson, Val);
}
void Insert (int &p, int Val, int Fa) {
if (!p)
Splay (p = Get (Val, Fa), 0);
else if (Val == Tr[p].Val)
++Tr[p].Cnt, Splay (p, 0);
else if (Val < Tr[p].Val)
Insert (Lson, Val, p);
else
Insert (Rson, Val, p);
}
void Delete(int Val) {
int p = Find (Root, Val);
if (!p)
return;
if (Tr[p].Cnt > 1) {
--Tr[p].Cnt, Splay (p, 0), Pull (p);
return;
}
Splay (p, 0);
int l = Lson, r = Rson;
while (Tr[l].Son[1])
l = Tr[l].Son[1];
while (Tr[r].Son[0])
r = Tr[r].Son[0];
Splay (l, 0), Splay (r, l);
Tr[r].Son[0] = 0, Pull (r), Pull (l);
}
int Get_Rank (int p, int Val) {
if (!p)
return 0;
if (Val == Tr[p].Val) {
int Res = Tr[Lson].Size + 1; Splay(p, 0);
return Res;
}
else if (Val < Tr[p].Val)
return Get_Rank (Lson, Val);
int Res = Tr[Lson].Size + Tr[p].Cnt;
return Get_Rank (Rson, Val) + Res;
}
int Get_Val (int p, int rank) {
if (!p)
return Inf;
if (Tr[Lson].Size >= rank)
return Get_Val (Lson, rank);
else if (Tr[Lson].Size + Tr[p].Cnt >= rank) {
Splay (p, 0);
return Tr[p].Val;
}
return Get_Val (Rson, rank - Tr[Lson].Size - Tr[p].Cnt);
}
int Get_Pre(int Val) {
int p = Root, Ret;
while (p) {
if (Tr[p].Val < Val)
Ret = Tr[p].Val, p = Rson;
else
p = Lson;
}
Splay (Root, 0);
return Ret;
}
int Get_Next(int Val) {
int p = Root, Ret;
while (p) {
if (Tr[p].Val > Val)
Ret = Tr[p].Val, p = Lson;
else
p = Rson;
}
Splay (Root, 0);
return Ret;
}
#undef Lson
#undef Rson
#undef Inf 0x3f3f3f3f
} Tree;
Treap.
// Treap
const int MAXN = 1e5 + 5;
struct Treap_Tree {
#define INF 0x3f3f3f3f
#define mod 998244353
struct Treap_Node {
int son[2], val, dat, cnt, size;
#define lson tr[p].son[0]
#define rson tr[p].son[1]
Treap_Node() {}
Treap_Node(int Val, int Dat, int Cnt, int Size) {
val = Val;
dat = Dat;
cnt = Cnt;
size = Size;
}
} tr[MAXN];
int tot, root;
int Get(int val) {
tr[++tot] = Treap_Node(val, rand() % mod, 1, 1);
tr[tot].son[0] = 0;
tr[tot].son[1] = 0;
return tot;
}
void Update(int p) { tr[p].size = tr[p].cnt + tr[lson].size + tr[rson].size; }
int Get_Rank(int p, int val) {
if (!p)
return 1;
if (val == tr[p].val)
return tr[lson].size + 1;
if (val < tr[p].val)
return Get_Rank(lson, val);
return tr[lson].size + tr[p].cnt + Get_Rank(rson, val);
}
int Get_Val(int p, int r) {
if (!p)
return INF;
if (tr[lson].size >= r)
return Get_Val(lson, r);
if (tr[lson].size + tr[p].cnt >= r)
return tr[p].val;
return Get_Val(rson, r - tr[lson].size - tr[p].cnt);
}
void Rotate(int &p, int t) {
int q = tr[p].son[!t];
tr[p].son[!t] = tr[q].son[t];
tr[q].son[t] = p;
p = q;
Update(tr[p].son[t]);
Update(p);
}
void Insert(int &p, int val) {
if (!p) {
p = Get(val);
return;
}
if (val == tr[p].val) {
tr[p].cnt++;
Update(p);
return;
}
if (val < tr[p].val) {
Insert(lson, val);
if (tr[p].dat < tr[lson].dat)
Rotate(p, 1);
} else {
Insert(rson, val);
if (tr[p].dat < tr[rson].dat)
Rotate(p, 0);
}
Update(p);
}
int Get_Pre(int x) {
int p = root, ret = -INF;
while (p) {
if (tr[p].val <= x) {
ret = tr[p].val;
p = rson;
} else
p = lson;
}
return ret;
}
int Get_Next(int x) {
int p = root, ret = INF;
while (p) {
if (tr[p].val >= x) {
ret = tr[p].val;
p = lson;
} else
p = rson;
}
return ret;
}
void Delete(int &p, int val) {
if (!p)
return;
if (val == tr[p].val) {
if (tr[p].cnt > 1) {
tr[p].cnt--;
Update(p);
return;
}
if (lson || rson) {
if (rson == 0 || tr[lson].dat > tr[rson].dat) {
Rotate(p, 1);
Delete(rson, val);
} else {
Rotate(p, 0);
Delete(lson, val);
}
Update(p);
} else
p = 0;
return;
}
if (val < tr[p].val)
Delete(lson, val);
else
Delete(rson, val);
Update(p);
}
#undef lson
#undef rson
} tree;
Template -「平衡树」的更多相关文章
- 「luogu3380」【模板】二逼平衡树(树套树)
「luogu3380」[模板]二逼平衡树(树套树) 传送门 我写的树套树--线段树套平衡树. 线段树上的每一个节点都是一棵 \(\text{FHQ Treap}\) ,然后我们就可以根据平衡树的基本操 ...
- Template -「整体二分」
写的简单.主要是留给自己做复习资料. 「BZOJ1901」Dynamic Rankings. 给定一个含有 \(n\) 个数的序列 \(a_1,a_2 \dots a_n\),需要支持两种操作: Q ...
- 「SCOI2014」方伯伯的 OJ 解题报告
「SCOI2014」方伯伯的 OJ 和列队有点像,平衡树点分裂维护即可 但是需要额外用个set之类的对编号查找点的位置 插入完了后记得splay,删除时注意特判好多东西 Code: #include ...
- LOJ 3184: 「CEOI2018」斐波那契表示法
题目传送门:LOJ #3184. 题意简述: 题目说得很清楚了. 题解: 首先需要了解「斐波那契数系」为何物. 按照题目中定义的斐波那契数列 \(F_n\),可以证明,每个非负整数 \(n\) 都能够 ...
- 「JSOI2011」任务调度
「JSOI2011」任务调度 传送门 一开始还在想写平衡树,看到 \(\text{TRANS}\) 操作后就晓得要用可并堆了. 这题好像就是个可并堆的板子题??? ADD 直接往对应的对里面加元素 D ...
- 「NOI2005」维护数列
「NOI2005」维护数列 传送门 维护过程有点像线段树. 但我们知道线段树的节点并不是实际节点,而平衡树的节点是实际节点. 所以在向上合并信息时要加入根节点信息. 然后节点再删除后编号要回退(栈), ...
- 「HNOI2004」宠物收养场
「HNOI2004」宠物收养场 传送门 对宠物和人各维护一棵平衡树,每次 \(\text{split}\) 的时候记得判一下子树是否为空,然后模拟就好了. 参考代码: #include <alg ...
- 「TJOI2013」最长上升子序列
「TJOI2013」最长上升子序列 传送门 这个 \(\text{DP}\) 应该都会撒: \[dp_i = \max_{j < i,a_j < a_i}\left\{dp_j\right ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
随机推荐
- Django学习——Django settings 源码、模板语法之传值、模板语法之获取值、模板语法之过滤器、模板语法之标签、自定义过滤器、标签、inclusion_tag、模板的导入、模板的继承
Django settings 源码 """ 1.django其实有两个配置文件 一个是暴露给用户可以自定义的配置文件 项目根目录下的settings.py 一个是项目默 ...
- Lab_1:练习1——理解通过make生成执行文件的过程
lab_0 清华大学ucore实验环境配置详细步骤!(小白入) lab_1 清华大学ucore bootload启动ucore os(预备知识) Lab_1:练习1--理解通过make生成执行文件的过 ...
- 墙裂推荐!一款 VM 大规模集群管理工具
关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ Google 发布了基础设施管理工具 VM Manager,可自动维护大型Compute En ...
- 论文阅读 Dynamic Graph Representation Learning Via Self-Attention Networks
4 Dynamic Graph Representation Learning Via Self-Attention Networks link:https://arxiv.org/abs/1812. ...
- 老生常谈系列之Aop--Spring Aop源码解析(二)
老生常谈系列之Aop--Spring Aop源码解析(二) 前言 上一篇文章老生常谈系列之Aop--Spring Aop源码解析(一)已经介绍完Spring Aop获取advice切面增强方法的逻辑, ...
- Web安全学习笔记 SQL注入中
Web安全学习笔记 SQL注入中 繁枝插云欣 --ICML8 权限提升 数据库检测 绕过技巧 一.权限提升 1. UDF提权 UDF User Defined Function,用户自定义函数 是My ...
- 记录一次用宝塔部署微信小程序Node.js后端接口代码的详细过程
一直忙着写毕设,上一次写博客还是元旦,大半年过去了.... 后面会不断分享各种新项目的源码与技术.欢迎关注一起学习哈! 记录一次部署微信小程序Node.js后端接口代码的详细过程,使用宝塔来部署. 我 ...
- scrapy架构与目录介绍、scrapy解析数据、配置相关、全站爬取cnblogs数据、存储数据、爬虫中间件、加代理、加header、集成selenium
今日内容概要 scrapy架构和目录介绍 scrapy解析数据 setting中相关配置 全站爬取cnblgos文章 存储数据 爬虫中间件和下载中间件 加代理,加header,集成selenium 内 ...
- windows获取高精度时间戳 精度100ns
#include <stdio.h> #include <Windows.h> int main(void){ LARGE_INTEGER ticks,Frequency; Q ...
- QC快速充电
QC快充 一.高通QC快充的介绍 二.识别充电类型的芯片介绍 三.QC充电曲线 四.如何在log中看QC充电类型 五.QC3识别错误 六.波形图 一.高通QC快充的介绍 高通QC快充技术,又称Quic ...