https://www.luogu.org/problemnew/show/P3369

Splay模板

 #include<iostream>
#include<cstdio>
using namespace std;
#define MAXN 100010
int n,sons[MAXN][],f[MAXN],size[MAXN],cnt[MAXN],value[MAXN],root,Size;
inline int read(){    //快读
int x=,ff=; char c=getchar();
while(c<''||c>'') { if(c=='-') ff=-; c=getchar(); }
while(''<=c&&c<='') { x=(x<<)+(x<<)+c-''; c=getchar(); }
return x*ff;
}
inline void clear(int x){  //清除节点x
f[x]=sons[x][]=sons[x][]=size[x]=cnt[x]=value[x]=;
}
inline int get_w(int p){
return sons[f[p]][]==p;
}
inline void update(int p){
if(p){
size[p]=cnt[p];
if(sons[p][]) size[p]+=size[sons[p][]];
if(sons[p][]) size[p]+=size[sons[p][]];
}
}
inline void rotate(int x){  //旋转节点x
int fa=f[x],gfa=f[f[x]],ws=get_w(x);
sons[fa][ws]=sons[x][ws^];  //father与son
f[sons[fa][ws]]=fa;
f[fa]=x;             //father与x
sons[x][ws^]=fa;
f[x]=gfa;            //x与grandfather
if(gfa) sons[gfa][sons[gfa][]==fa]=x;
update(x);
update(fa);
}
inline void Splay(int x){    //将x旋到root
for(int fa;fa=f[x];rotate(x))
if(f[fa])
rotate(get_w(x)==get_w(fa)?fa:x);  //若x,father,grandfather三个节点呈一条直线,就旋中间的节点
root=x;
}
void insert(int x){              //插入节点
if(!root){                 //如果树为空
Size++;
f[Size]=sons[Size][]=sons[Size][]=;
size[Size]=cnt[Size]=;
value[Size]=x;
root=Size;
return;
}
int now=root,fa=;
while(){
if(value[now]==x){  //如果已有的节点值=x
cnt[now]++;    //该节点数量+1
update(now);
update(fa);
Splay(now);    //旋到root,维护平衡树
return;
}
fa=now;
now=sons[now][x>value[now]];
if(!now){    如果旋到叶子节点,新开一个点
Size++;
sons[Size][]=sons[Size][]=;
f[Size]=fa;
size[Size]=cnt[Size]=;
value[Size]=x;
sons[fa][value[fa]<x]=Size;
update(fa);
Splay(Size);
return;
}
}
}
int find_num(int x){    //找大小顺序为x的节点的值
int now=root;
while(){
if(sons[now][]&&x<=size[sons[now][]]) now=sons[now][];  //左子树大小>x,则向左子树查询
else{
int temp=(sons[now][]?size[sons[now][]]:)+cnt[now];
if(x<=temp) return value[now];    //x包含在cnt[now]中
x-=temp;
now=sons[now][];
}
}
}
int find_rank(int x){        //查询值为x的点的大小编号
int now=root,ans=;
while(){
if(x<value[now]) now=sons[now][];
else{
ans+=sons[now][]?size[sons[now][]]:;
if(x==value[now]){
Splay(now);
return ans+;
}
ans+=cnt[now];
now=sons[now][];
}
}
}
inline int find_pre(){  //root的前驱即为左子树中最靠右的点
int now=sons[root][];
while(sons[now][]) now=sons[now][];
return now;
}
inline int find_suf(){
int now=sons[root][];
while(sons[now][]) now=sons[now][];
return now;
}
void delete_node(int x){  //删除节点x
find_rank(x);      //将x旋上去
if(cnt[root]>){
cnt[root]--;
update(root);
return;
}
if(!sons[root][]&&!sons[root][]){
clear(root); root=; return;
}
if(!sons[root][]){
int last=root;
root=sons[root][];
f[root]=;
clear(last);
return;
}
if(!sons[root][]){
int last=root;
root=sons[root][];
f[root]=;
clear(last);
return;
}
int last=root,pre=find_pre();    //将前驱旋上去,此时x为pre的右儿子,直接删除即可(类似于链表)
Splay(pre);
sons[root][]=sons[last][];
f[sons[last][]]=root;
clear(last);
update(root);
}
int main()
{
n=read();
int opt,x;
while(n--){
opt=read(); x=read();
switch(opt){
case : insert(x); break;
case : delete_node(x); break;
case : printf("%d\n",find_rank(x)); break;
case : printf("%d\n",find_num(x)); break;
case : insert(x);printf("%d\n",value[find_pre()]);delete_node(x); break;
case : insert(x);printf("%d\n",value[find_suf()]);delete_node(x); break;
}
}
return ;
}

【洛谷P3369】 (模板)普通平衡树的更多相关文章

  1. 【洛谷P3369】普通平衡树——Splay学习笔记(一)

    二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ...

  2. 洛谷.3369.[模板]普通平衡树(Splay)

    题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...

  3. 洛谷.3369.[模板]普通平衡树(fhq Treap)

    题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...

  4. 洛谷.3391.[模板]文艺平衡树(Splay)

    题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...

  5. 洛谷P3369 【模板】普通平衡树(Treap/SBT)

    洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...

  6. 【洛谷P3369】【模板】普通平衡树题解

    [洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...

  7. 洛谷P3369普通平衡树(Treap)

    题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...

  8. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  9. 绝对是全网最好的Splay 入门详解——洛谷P3369&BZOJ3224: Tyvj 1728 普通平衡树 包教包会

    平衡树是什么东西想必我就不用说太多了吧. 百度百科: 一个月之前的某天晚上,yuli巨佬为我们初步讲解了Splay,当时接触到了平衡树里的旋转等各种骚操作,感觉非常厉害.而第二天我调Splay的模板竟 ...

  10. 洛谷P3380 二逼平衡树

    线段树+平衡树 我!又!被!卡!常!了! 以前的splay偷懒的删除找前驱后继的办法被卡了QAQ 放一个在洛谷开O2才能过的代码..我太菜了.. #include <bits/stdc++.h& ...

随机推荐

  1. Apache Beam中的函数式编程理念

    不多说,直接上干货! Apache Beam中的函数式编程理念 Apache Beam的编程范式借鉴了函数式编程的概念,从工程和实现角度向命令式妥协. 编程的领域里有三大流派:函数式.命令式.逻辑式. ...

  2. hibernate框架的搭建

    1 导入所需的jar包 1 导入hibernate必须的jar包 2 导入驱动包 2 创建数据库,准备表,实体 1 创建hibernate数据库 CREATE DATABASE hibernate; ...

  3. 【iptables】规则的试验和查看

    1.存在桥接,查看桥接访客网络规则 ebtables -L 可以看到对不同的链的策略

  4. 【Linux】Linux系统启动过程

    1.Linux系统的启动过程并不是大家想象中的那么复杂,其过程可以分为5个阶段: 内核的引导. 运行 init. 系统初始化. 建立终端 . 用户登录系统. 1.Linux系统的启动过程并不是大家想象 ...

  5. iis6、iis7、apache设置mime类型

    1.IIS6添加方法. 打开iis,展开网站,右键要设置的站点--属性.找到“http头”选项卡--mime类型 进行设置添加. 截图以.ipa mime类型举例. 2.IIS7(iis7.5.iis ...

  6. C#字符串替换_无视大小写

    C#里的string.Replace是不能无视大小写的. 首先想到的是正则表达式,在网上查了下,果然有用正则表达式配合一些逻辑运算,实现无视大小写的字符串替换方法.但是正则表达式的方法用起来很麻烦,实 ...

  7. C++里创建 Trie字典树(中文词典)(一)(插入、遍历)

    萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...

  8. python占位符%s,%d,%r,%f

    input接收的所有输入默认都是字符串格式 1.%s代表字符串占位符 conn, client_addr = phone.accept() print(conn) print(client_addr) ...

  9. scss-@extend

    @extend指令用于共享规则和选择器之间的关系.它可以扩展所有其他类的样式在一个类中,也可应用于自己特定的样式. 查看如下scss@extend示例: .style{ font-size: 30px ...

  10. 【代码笔记】JTable 、TableModel的使用3

    在java中插入Table,并通过TableModel插入表格初始化状态后,如果需要第一行标题栏进行重命名,直接利用TableModel接口去实现列名修改,在图形显示中是无法实现的. 这里需要用到 J ...