FHQ 平衡树(二)
时间:2021-08-19
本文章向大家介绍FHQ 平衡树(二),主要包括FHQ 平衡树(二)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
FHQ 平衡树
这次以文艺平衡树为例讲解FHQ 平衡树维护区间信息
前言
没有PHQ基础的先看这个
平衡树(一)
区间操作
反转区间
假设反转区间[l,r]
拆分成三段x[1,l-1],y[l,r],z[r+1,n],然后操作中间区间y后合并
对区间用懒标记即可,懒标记标记左右儿子是否反转,然后分裂合并前需要下穿标记
具体看代码注释
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+10;
int tot=0,root;
struct node{
int val,l,r,size,dat;bool rev;//rev为标记
}t[maxn];
int nw(int val){
t[++tot].val=val;
t[tot].dat=rand();
t[tot].size=1;
return tot;
}
void push_up(int p){
t[p].size=t[t[p].l].size+t[t[p].r].size+1;
}
void push_down(int now){//标记左右儿子
swap(t[now].l,t[now].r);//儿子两需要交换
t[t[now].l].rev^=1;
t[t[now].r].rev^=1;
t[now].rev=0;//取消标记
}
void split(int now,int size,int &x,int &y){
if(!now)x=y=0;
else{
if(t[now].rev)push_down(now);//分裂前就应把标记下传
if(t[t[now].l].size<size){
x=now;//属于分裂大小为size的树
split(t[now].r,size-t[t[now].l].size-1/*减去左子树大小和根,继续分裂的剩下大小*/,t[now].r,y);//往右
}
else {
y=now;
split(t[now].l,size,x,t[now].l);//往左
}push_up(now);
}
}
int merge(int x,int y){
if(!x||!y) return x+y;
if(t[x].dat>t[y].dat){
if(t[x].rev)push_down(x);
t[x].r=merge(t[x].r,y);
push_up(x);return x;
}
else{
if(t[y].rev)push_down(y);
t[y].l=merge(x,t[y].l);
push_up(y);return y;
}
}
void reverse(int l,int r){
int x,y,z;
//分裂成三个区间
split(root,l-1,x,y);
split(y,r-l+1,y,z);
//y为中间区间的根
t[y].rev^=1;//中间区间,打上标记
root=merge(merge(x,y),z);
}
void dfs(int now){//中序遍历输出
if(!now)return ;
if(t[now].rev) push_down(now);
dfs(t[now].l);printf("%d ",t[now].val);
dfs(t[now].r);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) root=merge(root,nw(i));//建树
while(m--){
int l,r;scanf("%d%d",&l,&r);
reverse(l,r);
}dfs(root); return 0;
}
原文地址:https://www.cnblogs.com/guiyou/p/15163098.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 《闲扯Redis十》Redis 跳跃表的结构实现
- 图数据库HugeGraph源码解读 (1) —— 入门介绍
- String及StringTable(一):String源码解读
- 四、原型模式与建造者模式详解
- LeetCode 23. 移动零
- LeetCode 11. 盛最多水的容器
- 29.MyBatis体系结构与工作原理
- 五、代理模式详解
- 六、门面模式与装饰器模式详解
- 七、享元模式与门面模式详解
- 如何白嫖3个月的JetBrains全家桶(包括Java神器IDEA)
- 潘石屹用Python解决100个问题 | 打印菱形
- 八、适配器模式与桥接模式详解
- 九、委派模式与模板模式详解
- 白嫖JetBrains全家桶第二波与第三波