【洛谷P3369】 (模板)普通平衡树
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】 (模板)普通平衡树的更多相关文章
- 【洛谷P3369】普通平衡树——Splay学习笔记(一)
二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ...
- 洛谷.3369.[模板]普通平衡树(Splay)
题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...
- 洛谷.3369.[模板]普通平衡树(fhq Treap)
题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...
- 洛谷.3391.[模板]文艺平衡树(Splay)
题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...
- 【洛谷P3369】【模板】普通平衡树题解
[洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...
- 洛谷P3369普通平衡树(Treap)
题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 绝对是全网最好的Splay 入门详解——洛谷P3369&BZOJ3224: Tyvj 1728 普通平衡树 包教包会
平衡树是什么东西想必我就不用说太多了吧. 百度百科: 一个月之前的某天晚上,yuli巨佬为我们初步讲解了Splay,当时接触到了平衡树里的旋转等各种骚操作,感觉非常厉害.而第二天我调Splay的模板竟 ...
- 洛谷P3380 二逼平衡树
线段树+平衡树 我!又!被!卡!常!了! 以前的splay偷懒的删除找前驱后继的办法被卡了QAQ 放一个在洛谷开O2才能过的代码..我太菜了.. #include <bits/stdc++.h& ...
随机推荐
- Js常用的设计模式(1)——单例模式
<Practical Common Lisp>的作者 Peter Seibel 曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通 ...
- linux防火墙与端口设置
1.编辑iptables文件 # sudo vi /etc/sysconfig/iptables 添加如下一行 -A INPUT -p tcp -m state --state NEW -m tcp ...
- javascript获取后台传来的json
Mvc Razor视图引擎中 <script type="text/javascript"> var _temp = @(new MvcHtmlString(this. ...
- windows使用bat文件定时备份文件
遇到一个需求,需要备份Access数据库,Access生成的数据都保存在xx.mdb文件中,所以考虑使用windows任务 定时执行一个备份文件的bat文件来解决这个问题. backup.bat文件代 ...
- 关于消息推送的补充,主要介绍服务端的实现,包含object c 版本 c 版本 java 版本 php 版本 (转)
要实现消息推送功能,我们可以采用第三方(腾讯:信鸽:百度:云推送:极光推送:友盟):当然,因为各种原因,我们不能使用第三方的推送服务,那我们就需要自己编写服务端.在网上寻觅了很久,找到一篇很不错的讲解 ...
- 从零开始的全栈工程师——利用CSS3画一个正方体 ( css3 )
transform属性 CSS3的变形(transform)属性让元素在一个坐标系统中变形.transform属性的基本语法如下: transform:none | <transform-fun ...
- 首页的css
html,body{ margin:; padding:; background-color: lavenderblush; } a{ color:darkgray; } li{ list-style ...
- centOs升级
因为军佬放弃制作Centos7的网络重装包,又Centos7的安装引导和6有较大区别所以,选择曲线救国(技术不行,只能这样乱搞)前文:Centos6.9一键重装包https://ppx.ink/net ...
- Vue基础知识之vue-resource和axios
Vue基础知识之vue-resource和axios 原文链接:http://www.cnblogs.com/Juphy/p/7073027.html vue-resource Vue.js是数据驱 ...
- Bootstrap拟态框+支付宝首页
任务没完成,继续来!因为刚才网不好,我辛辛苦苦打了洋洋洒洒一大堆都没了! 我们今天主要是说一个简单的由Bootstrap和HTML5结合而成的小案例: 首先:由标题可得知,这是移动端,所以需要这样一串 ...