上文传送门:平衡树——splay 一 - yi_fan0305 - 博客园 (cnblogs.com)

OK,我们继续上文,来讲一些其他操作。

七、找排名为k的数

和treap的操作很像,都是通过比较左右子树和该节点的大小来查找。

ll k_th(int x)
{
int id=root;
if(siz[id]<x) return 0;
while(1)
{
int y=ch[id][0];
if(x>siz[y]+cnt[id])
{
x-=(siz[y]+cnt[id]);
id=ch[id][1];
}
else
{
if(siz[y]>=x) id=y;
else return val[id];
}
}
}

八、清理(一般删除之后用)

void cls(int x)
{
fa[x]=ch[x][0]=ch[x][1]=siz[x]=cnt[x]=val[x]=0;//清理干净,以绝后患
}

这里要注意,这里只是把该节点的信息删除了,不要忘记把父亲的关系也切断

九、递归建树

相较于单点一个一个插入,在已知点权的情况下,可以直接递归建一棵树,这样效率更高

但是,要注意你是根据数据的下标建的树还是点权建的树,依据不同,操作也不同

其次,为了方便区间操作,一般留出第一个位置(a[1])和最后一个位置,增加哨兵

a[1]=-INF;
for(rint i=2;i<=n+1;++i)
a[i]=i-1;
a[n+2]=INF;
root=build(1,n+2,0);
int build(int l,int r,int f)//l 左边界 r 右边界 f 初始化为0
{
if(l>r) return 0;
int mid=l+r>>1;
fa[mid]=f;
ch[mid][0]=build(l,mid-1,mid);
ch[mid][1]=build(mid+1,r,mid);
pushup(mid);
return mid;
}

十、下传懒标记

void pushdown(int id)
{
if(!lazy[id]) return;
//进行操作......
}

在一些操作中,如旋转、find、翻转、加减,等等,一定不要忘记pushdown

例如:旋转的懒标记下传

void spin(int x)
{
rint y=fa[x],z=fa[y],d=(x==ch[y][1]);
pushdown(y),pushdown(x);//懒标记下传
ch[z][ch[z][1]==y]=x,fa[x]=z;
ch[y][d]=ch[x][d^1],fa[ch[x][d^1]]=y;
ch[x][d^1]=y,fa[y]=x;
pushup(y);
pushup(x);
}

十一、找数x的排名

这个其实与前面的find一样,只是返回左子树的大小即可

insert(-INF);
insert(INF);
find(x);
printf("%lld\n",siz[ch[root][0]]+(val[root]<x?cnt[root]:0));
void find(ll x)
{
int u=root;
if(!u) return;//不存在该节点,直接返回
while(ch[u][x>val[u]]&&x!=val[u])//找到该节点的位置
u=ch[u][x>val[u]];
splay(u,0);//伸展
}

接下来就是区间操作的主场了

区间操作:

区间操作:指定区间(l~r),查找排序为l-1的节点并伸展至根,查找排序为r+1的节点并伸展至root下,则节点r+1的左子树就是所要的区间。为了操作的方便,在不影响的结果的情况下,可以在两端增加哨兵。

如图依旧扒的教练的

根据二叉查找树的性质,R+1的左孩子就是L--R范围的数据

区间操作都是以这个思路为基础的,前面的删点操作也是运用的这个思路,明白这个,后面才可以进行

pushdown函数随时用上

每次伸展时都要保证懒标记已下传

void check(int now)//保证所有懒标记都下传了
{
int id=root;
int k=root;
while(1)
{
pushdown(k);
if(now==k)break;
if(now>k)k=ch[k][1];
else k=ch[k][0];
}
}

十二、翻转

操作比较简单,交换左右孩子然后下传懒标记即可,但要注意,一棵树被翻转了两次并没有发生变化,所以它的懒标记只有1和0两种,主要注意pushdown函数就好了

建树时要根据下标建树

void pushdown(int id)
{
if(!rev[id]) return;
swap(ch[id][0],ch[id][1]);
rev[ch[id][0]]^=1;
rev[ch[id][1]]^=1;
rev[id]=0;
}
void rever(int l,int r)
{
int pre=find(l-1),nxt=find(r+1);
splay(pre,0);
splay(nxt,pre);
int x=ch[nxt][0];
rev[x]^=1;
}

十三、区间加、减

和线段树差不多,其实线段树能做的,平衡树也能做到,平衡树能很简单的做到的,线段树就不一定能做到了

在伸展操作之前,一定要保证懒标记都下传了

void pushup(int id)
{
sum[id]=sum[ch[id][0]]+sum[ch[id][1]]+val[id];
siz[id]=siz[ch[id][0]]+siz[ch[id][1]]+1;
}
void add(int id,ll v)
{
if(!id) return;
sum[id]+=siz[id]*v;
laz[id]+=v;
val[id]+=v;
}
void pushdown(int id)
{
if(!laz[id]) return;
add(ch[id][0],laz[id]);
add(ch[id][1],laz[id]);
laz[id]=0;
}
void change(int l,int r,int v)
{
int pre=get(l,0),nxt=get(r,1);
splay(pre,0);splay(nxt,pre);
add(ch[nxt][0],v);
pushup(nxt);
pushup(pre);
}

十四、区间求和

和线段树操作几乎一模一样

void query(int l,int r)
{
int pre=get(l,0),nxt=get(r,1);
splay(pre,0);splay(nxt,pre);
printf("%lld",sum[ch[nxt][0]]);
}

一般用的应该就这些了吧,如果有,我会补充的QWQ!

来自未来的链接:

平衡树——splay 三 - yi_fan0305 - 博客园 (cnblogs.com)

平衡树——splay 二的更多相关文章

  1. 平衡树——splay 三

    前文链接: 平衡树--splay 一 - yi_fan0305 - 博客园 (cnblogs.com) 平衡树--splay 二 - yi_fan0305 - 博客园 (cnblogs.com) 再补 ...

  2. 平衡树——splay 一

    splay 一种平衡树,同时也是二叉排序树,与treap不同,它不需要维护堆的性质,它由Daniel Sleator和Robert Tarjan(没错,tarjan,又是他)创造,伸展树是一种自调整二 ...

  3. [洛谷P3391] 文艺平衡树 (Splay模板)

    初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...

  4. hiho #1329 : 平衡树·Splay

    #1329 : 平衡树·Splay 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. ...

  5. 【BZOJ3224】Tyvj 1728 普通平衡树 Splay

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

  6. BZOJ3224/洛谷P3391 - 普通平衡树(Splay)

    BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...

  7. Hihocoder 1329 平衡树·Splay(平衡树)

    Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...

  8. 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay

    [阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...

  9. luoguP3391[模板]文艺平衡树(Splay) 题解

    链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...

随机推荐

  1. windows 存储和切换 ip 配置

    我的虚拟机用的是桥接模式,在公司使用时设置的是静态 ip,但网段和家里面的不一样,就导致在公司和家里,我需要频繁修改 ipv4 的配置以适应不同的网络环境 Simple-IP-Config 工具解决了 ...

  2. 难对齐、难保障、难管理?一文了解字节跳动如何解决数据SLA治理难题

    基于字节跳动分布式治理的理念,数据平台数据治理团队自研了SLA保障平台,目前已在字节内部得到广泛使用,并支持了绝大部分数据团队的SLA治理需求,每天保障的SLA链路数量过千,解决了数据SLA难对齐.难 ...

  3. Python数据分析--工具安装及Numpy介绍(1)

    Anaconda 是一个跨平台的版本,通过命令行来管理安装包.进行大规模数据处理.预测分析和科学计算.它包括近 200 个工具包,大数据处理需要用到的常见包有 NumPy . SciPy . pand ...

  4. 【freertos】008-内存管理

    前言 本章主要讲解内部存储空间(RAM)的管理. 详细分析heap5方案. 参考: 李柱明博客 https://freertos.blog.csdn.net/article/details/51606 ...

  5. CF1681F Unique Occurrences

    题意:一棵树,问每条路径上只出现一次的值的个数的和. 思路: 显然想到考虑边贡献.每条边权下放到下面的哪个点.\(up_i\)为上面第一个点权等于它的点.我们需要一个子树内点权等于它的点(如果满足祖孙 ...

  6. vs2022+resharper C++ = 拥有一个不输clion的代码体验

    这篇文章详细讲一下resharper C++在vs2022中的配置,让他拥有跟clion一样好用的代码补全功能. 为什么clion写代码体验很好好用为啥还要用vs呢,因为网上很多教程都是基于visua ...

  7. autohotkey(AHK)实现箭头映射

    起因 在主力本上使用了AHK实现alt ijkl的箭头映射,在另一个本子上怎么都不习惯,于是网上找教程,找了半天... 因为大家习惯了快捷键都不一样,为了避免以后浪费时间,因此开此文记录. 操作 ht ...

  8. element ui FORM表单

    form表单 Form-Item Slot [label] 旧版语法 <el-form-item label="活动名称" prop="name"> ...

  9. BUUCTF-另一个世界

    另一个世界 010editor 打开最下方发现011开头字符串,应该是二进制 得到flag 看也有师傅写的是说八个一组转ascii码,现在也不是很理解啥意思.贴一下其他师傅的python脚本,算出的结 ...

  10. <%= %> <%- %> <% %>是什么意思?

    .ejs文件后缀的数据渲染,这是服务器端的.把 .html改成 .ejs, (1)<%= %>相当于html中的innerTEXT,导出不包含标签 . (2)<%- %>相当于 ...