洛谷-P3369-普通平衡树(Treap)
题目传送门
标题说平衡树,那么应该AVL,红黑树都能过,但是这次做这题主要是学习Treap,所以花了几天搞出了这题。其他方法以后再说吧
- Treap(带旋转)
#include <bits/stdc++.h>
using namespace std;
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct Treap {
int son[];
int val, rand;
int cnt, size;
} node[MAXN];
int root, tot;
void update(int i) {
int ls = node[i].son[];
int rs = node[i].son[];
node[i].size = node[ls].size + node[rs].size + node[i].cnt;
}
void rotate(int& r, int index) {
int k = node[r].son[index ^ ];
node[r].son[index ^ ] = node[k].son[index];
node[k].son[index] = r;
update(r); update(k);
r = k;
}
void insert(int& r, int v) {
if (r == ) {
r = ++ tot;
node[r].val = v;
node[r].rand = rand();
node[r].size = node[r].cnt = ;
return;
}
if (node[r].val == v) {
node[r].size ++;
node[r].cnt ++;
return;
}
int index = v > node[r].val;
insert(node[r].son[index], v);
if (node[node[r].son[index]].rand < node[r].rand) rotate(r, index ^ );
update(r);
}
void erase(int& r, int v) {
if (r == ) return;
if (v == node[r].val) {
if (node[r].cnt > ) {
node[r].cnt --;
node[r].size --;
return;
}
if (node[r].son[] == || node[r].son[] == ) {
r = node[r].son[] + node[r].son[];
} else {
int ls = node[r].son[];
int rs = node[r].son[];
int index = node[ls].rand < node[rs].rand;
rotate(r, index);
erase(node[r].son[index], v);
}
} else {
int index = v > node[r].val;
erase(node[r].son[index], v);
}
update(r);
}
int get_rank(int r, int v) {
int size = node[node[r].son[]].size;
int cnt = node[r].cnt;
if (node[r].val == v) return size + ;
if (node[r].val > v) return get_rank(node[r].son[], v);
if (node[r].val < v) return size + cnt + get_rank(node[r].son[], v);
}
int get_val(int r, int rk) {
int size = node[node[r].son[]].size;
int cnt = node[r].cnt;
if (rk < size + ) return get_val(node[r].son[], rk);
if (rk >= size + && rk <= size + cnt) return node[r].val;
if (rk > size + cnt) return get_val(node[r].son[], rk - size - cnt);
}
int get_pre(int r, int v) {
if (r == ) return -INF;
if (node[r].val >= v) return get_pre(node[r].son[], v);
else return max(node[r].val, get_pre(node[r].son[], v));
}
int get_suc(int r, int v) {
if (r == ) return INF;
if (node[r].val <= v) return get_suc(node[r].son[], v);
else return min(node[r].val, get_suc(node[r].son[], v));
}
int main() {
srand(time(NULL));
int n; scanf("%d", &n);
for (int i = ; i <= n; i++) {
int opt, x;
scanf("%d%d", &opt, &x);
if (opt == ) insert(root, x);
if (opt == ) erase(root, x);
if (opt == ) printf("%d\n", get_rank(root, x));
if (opt == ) printf("%d\n", get_val(root, x));
if (opt == ) printf("%d\n", get_pre(root, x));
if (opt == ) printf("%d\n", get_suc(root, x));
}
return ;
}学到的第二个用随机数的算法,所以这个Treap的高度也是有的随机的。但是起码不太可能退化成链状。
- Treap(无旋转)
#include <bits/stdc++.h>
using namespace std;
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct Treap {
int ls, rs;
int val, rand;
int size;
} node[MAXN];
int tot, root;
int add_node(int v) {
int i = ++tot;
node[i].val = v;
node[i].rand = rand();
node[i].ls = node[i].rs = ;
node[i].size = ;
return i;
}
void split(int rt, int& a, int& b, int v) {
if (rt == ) {
a = b = ;
return;
}
if (node[rt].val <= v) {
a = rt;
split(node[rt].rs, node[a].rs, b, v);
} else {
b = rt;
split(node[rt].ls, a, node[b].ls, v);
}
node[rt].size = node[node[rt].ls].size + node[node[rt].rs].size + ;
}
void merge(int& rt, int a, int b) {
if (a == || b == ) {
rt = a + b;
return;
}
if (node[a].rand < node[b].rand) {
rt = a;
merge(node[rt].rs, node[a].rs, b);
} else {
rt = b;
merge(node[rt].ls, a, node[b].ls);
}
node[rt].size = node[node[rt].ls].size + node[node[rt].rs].size + ;
}
void insert(int& rt, int v) {
int x = , y = ;
split(rt, x, y, v);
merge(x, x, add_node(v));
merge(rt, x, y);
}
void erase(int&rt, int v) {
int x = , y = , z = ;
split(rt, x, z, v);
split(x, x, y, v - );
merge(y, node[y].ls, node[y].rs);
merge(x, x, y);
merge(rt, x, z);
}
int get_rank(int rt, int v) {
int x = , y = ;
split(rt, x, y, v - );
int rk = node[x].size + ;
merge(rt, x, y);
return rk;
}
int get_val(int rt, int rk) {
int size = node[node[rt].ls].size;
if (rk < size + ) return get_val(node[rt].ls, rk);
if (rk == size + ) return node[rt].val;
if (rk > size + ) return get_val(node[rt].rs, rk - size - );
}
int get_pre(int rt, int v) {
int x = , y = ;
split(rt, x, y, v - );
int pre = get_val(x, node[x].size);
merge(rt, x, y);
return pre;
}
int get_suc(int rt, int v) {
int x = , y = ;
split(rt, x, y, v);
int suc = get_val(y, );
merge(rt, x, y);
return suc;
}
int main() {
srand(time(NULL));
int n; scanf("%d", &n);
for (int i = ; i <= n; i++) {
int opt, x;
scanf("%d%d", &opt, &x);
if (opt == ) insert(root, x);
if (opt == ) erase(root, x);
if (opt == ) printf("%d\n", get_rank(root, x));
if (opt == ) printf("%d\n", get_val(root, x));
if (opt == ) printf("%d\n", get_pre(root, x));
if (opt == ) printf("%d\n", get_suc(root, x));
}
return ;
}昨天看懂了带旋转的Treap,今天来写无旋转的Treap,感觉确实是比带旋转的好敲而且好懂,关键就是理解split()和merge()两个核心函数。
洛谷-P3369-普通平衡树(Treap)的更多相关文章
- [洛谷P3369] 普通平衡树 Treap & Splay
这个就是存一下板子...... 题目传送门 Treap的实现应该是比较正经的. 插入删除前驱后继排名什么的都是平衡树的基本操作. #include<cstdio> #include< ...
- 洛谷P3369普通平衡树(Treap)
题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...
- 洛谷P3369 普通平衡树
刚学平衡树,分别用了Splay和fhq-treap交了一遍. 这是Splay的板子,貌似比较短? Splay #include <iostream> #include <cstdio ...
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...
- 【洛谷P3369】【模板】普通平衡树题解
[洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...
- [洛谷P3391] 文艺平衡树 (Splay模板)
初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...
- 绝对是全网最好的Splay 入门详解——洛谷P3369&BZOJ3224: Tyvj 1728 普通平衡树 包教包会
平衡树是什么东西想必我就不用说太多了吧. 百度百科: 一个月之前的某天晚上,yuli巨佬为我们初步讲解了Splay,当时接触到了平衡树里的旋转等各种骚操作,感觉非常厉害.而第二天我调Splay的模板竟 ...
- BZOJ3223/洛谷P3391 - 文艺平衡树
BZOJ链接 洛谷链接 题意 模板题啦~2 代码 //文艺平衡树 #include <cstdio> #include <algorithm> using namespace ...
- BZOJ3224/洛谷P3391 - 普通平衡树(Splay)
BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...
- 洛谷 P3391 文艺平衡树
题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 --b ...
随机推荐
- python里的文件I/O
Python 文件I/O 本章只讲述所有基本的的I/O函数,更多函数请参考Python标准文档. 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个用逗号隔开的表达式.此函数把你 ...
- BZOJ 3197 [Sdoi2013]assassin
题解: 树上Hash 首先重心在边上就把边分裂 以重心为根建树,这样两个根一定对应 然后f[i][j]表示i匹配另一棵的j节点的最小代价 把他们的儿子摘出来做最小权匹配即可 #include<i ...
- luogu P4219 [BJOI2014]大融合
题解:原来LCT也能维护子树信息,我太Naive了 用LCT维护当前子树节点个数 具体做法维护siz[x]=当前Splay子树和指向当前Splay子树的虚边所代表的节点个数 auxsiz[x]=指向x ...
- 68.ORM查询条件:date,time,year,week_day等
1. date: 首先查看数据库中article表的信息,由表中的create_time字段可以看出时间为2020.2.5 打印出查询的结果: <QuerySet []>:但是查询的结果为 ...
- WOJ 1542 Countries 并查集转化新点+最短路
http://acm.whu.edu.cn/land/problem/detail?problem_id=1542 今天做武大的网赛题,哎,还是不够努力啊,只搞出三个 这个题目一看就是个最短路,但是题 ...
- 201609-2 火车购票 Java
思路待补充 import java.util.Scanner; class Main{ public static void main(String[] args) { //100个座位 int[] ...
- zabbix中文乱码解决
问题现象: zabbix字体修改成中文后监控显示乱码 原因: 该问题是由于zabbix默认使用的是“DejaVuSans.ttf”(zabbix3.2.7默认使用的是“graphfont.ttf”), ...
- 吴裕雄--天生自然JAVA线程编程笔记:创建线程
public class ThreadRuning extends Thread{ public ThreadRuning(String name){ //重写构造,可以对线程添加名字 super(n ...
- 注册网站 captcha reCHAPTCHA 错误
原因 出现这个错误,是因为注册和提交时候,没有正确输出验证码导致的.网站可能会为了防止恶意注册,而使用验证码.如果验证码没有被正确加载或验证,就会出现相关错误. 解决方案 如果是访问类似kaggle, ...
- reference-based measure|Distribution-based measure|密码子使用偏向性
生命组学 密码子使用偏向性是指同义密码子使用频率不同. 影响因素:1.GC2.横向基因转移3.selection 转录偏好于多的tRNA. 同种氨基酸但有密码子使用偏向. ============== ...