#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
//欢迎阅读胡小兔的平衡树板子 =v=
const int N = 100005;
int n, root, idx, val[N], fa[N], ls[N], rs[N], sze[N], cnt[N];
#define which(x) (ls[fa[(x)]] == (x)) //判断x的"方向": x是左儿子还是右儿子 void upt(int x){ //update: 更新sze[x]
sze[x] = sze[ls[x]] + sze[rs[x]] + cnt[x];
}
void rotate(int x){ //如果x是左儿子则右旋,右儿子则左旋
int y = fa[x], z = fa[y], b = which(x) ? rs[x] : ls[x], dir = which(y);
which(x) ? (rs[x] = y, ls[y] = b) : (ls[x] = y, rs[y] = b);
fa[y] = x, fa[b] = y, fa[x] = z;
if(z) dir ? ls[z] = x : rs[z] = x;
upt(y), upt(x); //记得旋转之后更新大小,由下往上更新,此时y在下而x在上
}
void splay(int x){//将x旋转至根节点
while(fa[x]){//原则:为了尽可能使树平衡,如果x和fa[x]方向相同则先旋转fa再旋转x,否则旋转两次x
if(fa[fa[x]]){
if(which(x) == which(fa[x])) rotate(fa[x]);
else rotate(x);
}
rotate(x);
}
root = x; //记得更新根节点
}
int find(int x){ //找到值为x的节点; 如果没有则返回
int cur = root, last = 0;
while(cur && val[cur] != x){
last = cur;
if(x < val[cur]) cur = ls[cur];
else cur = rs[cur];
}
return cur ? cur : last;
}
int getmin(int x){ //找子树x中最小的点的编号
while(ls[x]) x = ls[x];
return x;
}
int getmax(int x){ //找子树x中最大的点的编号
while(rs[x]) x = rs[x];
return x;
}
void insert(int x){ //插入一个数
int cur = find(x); //找到值最相近的节点的编号
if(cur && val[cur] == x) return (void)(cnt[cur]++, sze[cur]++, splay(cur)); //如果已存在这个节点,则cnt++
val[++idx] = x, fa[idx] = cur, cnt[idx] = sze[idx] = 1;// 如果不存在这个节点,则新增一个节点
if(cur) x < val[cur] ? ls[cur] = idx : rs[cur] = idx;
splay(idx);
}
void erase(int x){
int cur = find(x);
splay(cur);
if(cnt[cur] > 1) cnt[cur]--, sze[cur]--; //如果这个值去掉一个之后还存在,则只要cnt--就好了
else if(!ls[cur] || !rs[cur]) root = ls[cur] + rs[cur], fa[root] = 0; //如果至少一个儿子为空,则让那个儿子做根节点;如果两个儿子均为空,则说明删除这个点后整棵树为空
else{
fa[ls[cur]] = 0; //让左子树中最大的点做根节点,右子树做新根节点的右子树
int u = getmax(ls[cur]);
splay(u);
rs[u] = rs[cur], fa[rs[cur]] = u;
upt(u);
}
}
int getkth(int k){ //找排名为k的数,类似权值线段树
int cur = root;
while(cur){
if(sze[ls[cur]] >= k) cur = ls[cur];
else if(sze[ls[cur]] + cnt[cur] >= k) return val[cur];
else k -= sze[ls[cur]] + cnt[cur], cur = rs[cur];
}
return val[cur];
}
int getrank(int x){ //求x的排名
int cur = find(x);
splay(cur);
return sze[ls[cur]] + 1;
}
int getpre(int x){
int cur = find(x);
if(val[cur] < x) return val[cur];
splay(cur);
return val[getmax(ls[cur])];
}
int getnxt(int x){
int cur = find(x);
if(val[cur] > x) return val[cur];
splay(cur);
return val[getmin(rs[cur])];
}
int main(){
read(n);
while(n--){
int op, x;
read(op), read(x);
if(op == 1) insert(x);
if(op == 2) erase(x);
if(op == 3) write(getrank(x)), enter;
if(op == 4) write(getkth(x)), enter;
if(op == 5) write(getpre(x)), enter;
if(op == 6) write(getnxt(x)), enter;
}
return 0;
}

BZOJ 3224 普通平衡树 | 平衡树模板的更多相关文章

  1. 【BZOJ 3224】普通平衡树 模板题

    删除节点时把节点splay到根: 然后把根左子树的最右边节点splay到根的左孩子上: 然后删除就可以了: 我的教训是删根的时候根的右孩子的父亲指针一定要记得指向根的左孩子!!! my AC code ...

  2. BZOJ 3224 SBT 普通平衡树

    复习了一下SBT的模板,但是BZOJ不知道为什么注册不了,所以就没交,测了样例能过! #include <bits/stdc++.h> #include<algorithm> ...

  3. 【BZOJ 3224】 普通平衡树

    [题目链接] 点击打开链接 [算法] 本题是Splay模板题,值得一做! [代码] #include<bits/stdc++.h> using namespace std; #define ...

  4. BZOJ 3224 普通平衡树(Treap模板题)

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 14301  Solved: 6208 [Submit][ ...

  5. Luogu 3369 / BZOJ 3224 - 普通平衡树 - [无旋Treap]

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 https://www.luogu.org/problemnew/show/P3 ...

  6. 普通平衡树(bzoj 3224)

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...

  7. BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 7390  Solved: 3122 [Submit][S ...

  8. BZOJ 3224: Tyvj 1728 普通平衡树 or 洛谷 P3369 【模板】普通平衡树-Splay树模板题

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 22483  Solved: 10130[Submit][S ...

  9. BZOJ 3224 Tyvj 1728 普通平衡树模板

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 题目大意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以 ...

  10. fhq_treap || BZOJ 3224: Tyvj 1728 普通平衡树 || Luogu P3369 【模板】普通平衡树

    题面:[模板]普通平衡树 代码: #include<cstdio> #include<cstring> #include<iostream> #include< ...

随机推荐

  1. 【SIKIA计划】_03_C#初级教程 (2015版)笔记

    Win32 API是微软的操作系统Windows提供给开发人员的编程接口,它决定了我们开发的Windows应用程序的能力.MFC是微软为开发人员提供的类库,在某种意义上是对Win32 API的封装.M ...

  2. 自动分配ip的方法- 【Linux】

    1.  查看本机无线网络使用的网卡 2.  设置vbox的网络连接为桥接,并选择本机无线网络对应的网卡 3.  进入系统,输入ifconfig命令,记录下系统的HWaddr 4.  修改系统ip配置文 ...

  3. docker server gave HTTP response to HTTPS client 问题处理办法

    vi /etc/docker/daemon.json [root@localhost ~]# cat /etc/docker/daemon.json {"insecure-registrie ...

  4. Spring学习(5):DI的配置

    一.  一些概念 应用程序中说的依赖一般指类之间的关系. 泛化:表示类与类之间的继承关系.接口与接口之间的继承关系: 实现:表示类对接口的实现: 依赖:当类与类之间有使用关系时就属于依赖关系,不同于关 ...

  5. Netty源码分析第5章(ByteBuf)---->第3节: 缓冲区分配器

    Netty源码分析第五章: ByteBuf 第三节: 缓冲区分配器 缓冲区分配器, 顾明思议就是分配缓冲区的工具, 在netty中, 缓冲区分配器的顶级抽象是接口ByteBufAllocator, 里 ...

  6. DP使用GUI推送WIN客户端是报110:1022错误的解决办法

    在使用GUI推送WIN客户端时,输入用户名和密码后报错: [Critical 110::1022]  Cannot connect to the SCM (Service Control Manage ...

  7. 持续更新 | 想不到的key

    前言 开坑写一些我认为比较巧妙的东西想不到的东西 正文 判断回文串的时候 考虑一下枚举中心位往两边扩展 最大子矩阵与单调栈 遇难则反系列 算合法可以转换成算不合法.同理,不合法转换成合法计算有时也会简 ...

  8. 基于spec评论作品

    组名:杨老师粉丝群 组长:乔静玉 组员:吴奕瑶  刘佳瑞  公冶令鑫  杨磊  杨金铭  张宇  卢帝同 一.测试目标:拉格朗日2018——飞词 下面是他们的小游戏在运行时的一些截图画面: 1.开始: ...

  9. Sqlite数据库初步的了解

    转载与:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0714/1438.html    来自:泡在网上的日子. 和其他数据库一 ...

  10. Git管理分支

    管理分支:git branch 直至现在为止,我们的项目版本库一直都是只有一个分支 master.在 git 版本库中创建分支的成本几乎为零,所以,不必吝啬多创建几个分支.下面列举一些常见的分支策略, ...