BST-splay板子 - 维护一个分裂和合并的序列
splay 均摊复杂度 \(O(\log n)\) 证明: https://www.cnblogs.com/Mr-Spade/p/9715203.html
我这个 splay 有两个哨兵节点,分别是1和n+2。其实只需要一个哨兵节点就行,但是,为了美观和对称……
560ms 6.19MB
void splay(Node* &o,int x) 把左数第 x 个元素移动到根节点。
Node* merge(Node* left,Node* right) 把left树与right树合并。
void split(Node *o,int k,Node *&left,Node *&right) 把o这棵树前k个元素分裂到left树中,剩下的分裂到right树中。
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define IL inline
#define ri register int
typedef long long LL;
struct Node *null;
struct Node {
Node *ch[2];
int v,sz,cnt,flip;
IL Node() {}
IL Node(int v):v(v){ch[0]=ch[1]=null;flip=0;sz=cnt=1;}
IL int cmp(int k) const {
int d = k - ch[0]->sz;
if(d == 1) return -1;
return d > 0;
}
IL void upd() { sz = cnt + ch[0]->sz + ch[1]->sz;}
IL void pushdown() {
if(flip) {
flip = 0;
swap(ch[0],ch[1]);
ch[0]->flip ^= 1;
ch[1]->flip ^= 1;
}
}
};
IL void initnull() { null = new Node(); null->sz = null->v = null->cnt = null->flip = 0;}
IL void rotate(Node *&o,int d) {
Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o;
o->upd(); k->upd(); o = k;
}
void splay(Node* &o,int k) {
o->pushdown();
int d = o->cmp(k);
if(d == 1) k -= o->ch[0]->sz + o->cnt;
if(d != -1) {
Node* p = o->ch[d];
p->pushdown();
int d2 = p->cmp(k);
int k2 = (d2 == 0 ? k : k - p->ch[0]->sz - p->cnt);
if(d2 != -1) {
splay(p->ch[d2],k2);
if(d == d2) rotate(o,d^1); else rotate(o->ch[d],d);
}
rotate(o,d^1);
}
}
IL Node* merge(Node* left,Node* right) {
splay(left,left->sz);
left->ch[1] = right;
left->upd();
return left;
}
IL void split(Node* o,int k,Node *&left, Node *&right) {
splay(o,k);
left = o;
right = o->ch[1];
o->ch[1] = null;
left->upd();
}
const int N = 1e5 + 9;
int n,m,valcnt;
int val[N];
Node *root;
IL Node* build(int sz) {
if(!sz) return null;
Node *l = build(sz/2);
Node *o = new Node(val[++valcnt]);
o->ch[0] = l; o->ch[1] = build(sz-sz/2-1);
o->upd();
return o;
}
IL void init(int sz) {
initnull(); root = null;
for(int i=0;i<=n+2;i++) val[i] = i;
valcnt = 0;
root = build(sz);
}
vector<int> ans;
void print(Node *o) {
if(o == null) return;
o->pushdown();
print(o->ch[0]);
ans.push_back(o->v);
print(o->ch[1]);
}
int main() {
scanf("%d%d",&n,&m);
init(n+2);
// print(root);
// printf("anscnt=%d\n",anscnt);
// for(int i=1;i<anscnt-1;i++) printf("%d ",ans[i]-1);
// printf("\n");
while(m--) {
int a,b; scanf("%d%d",&a,&b);
Node *left,*mid,*right,*o;
split(root,a,left,o);
split(o,b-a+1,mid,right);
//if(root == null) printf("opsplit:root == null\n");
mid->flip ^= 1;
root = merge(merge(left,mid),right);
//if(root == null) printf("opmerge:root == null\n");
}
ans.clear();
print(root);
//if(root == null) printf("end:root == null\n");
//printf("anscnt=%d\n",anscnt);
for(int i=1;i<ans.size()-1;i++) printf("%d ",ans[i]-1);
return 0;
}
BST-splay板子 - 维护一个分裂和合并的序列的更多相关文章
- 模板——伸展树 splay 实现快速分裂合并的序列
伸展操作:将treap中特定的结点旋转到根 //将序列中从左数第k个元素伸展到根,注意结点键值保存的是原序列id void splay(Node* &o, int k) { ] == NULL ...
- [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)
解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...
- POJ - 3481 splay板子
Double Queue 默写splay板子 很多细节问题... #include<cstdio> #include<iostream> using namespace std ...
- 区间树Splay——[NOI2005]维护数列
无指针Splay超详细讲解 区间树这玩意真TM玄学. 学这东西你必须要拥有的 1.通过[模板]文艺平衡树(Splay),[模板]普通平衡树,GSS3 - Can you answer these qu ...
- BST,Splay平衡树学习笔记
BST,Splay平衡树学习笔记 1.二叉查找树BST BST是一种二叉树形结构,其特点就在于:每一个非叶子结点的值都大于他的左子树中的任意一个值,并都小于他的右子树中的任意一个值. 2.BST的用处 ...
- Java中使用IO流实现大文件的分裂与合并
文件分割应该算一个比较实用的功能,举例子说明吧比如说:你有一个3G的文件要从一台电脑Copy到另一台电脑, 但是你的存储设备(比如SD卡)只有1G ,这个时候就可以把这个文件切割成3个1G的文件 ,分 ...
- [bzoj] 1588 营业额统计 || Splay板子题
原题 给出一个n个数的数列ai ,对于第i个元素ai定义\(fi=min(|ai-aj|) (1<=j<i)\),f1=a1,求\(/sumfi\) Splay板子题. Splay讲解:h ...
- BZOJ 3224 Tyvj 1728 普通平衡树 | Splay 板子+SPlay详细讲解
下面给出Splay的实现方法(复杂度证明什么的知道是 nlogn 就可以啦) 首先对于一颗可爱的二叉查找树,是不能保证最坏nlogn的复杂度(可以想象把一个升序序列插入) (二叉查找树保证左子树元素大 ...
- BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)
BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...
- HDU 5945 维护一个单调队列 dp
Fxx and game Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Tot ...
随机推荐
- 2018-8-29-dotnet-core-2.1-使用阶梯编译
title author date CreateTime categories dotnet core 2.1 使用阶梯编译 lindexi 2018-08-29 08:49:12 +0800 201 ...
- 从大数据平台CDP的架构看大数据的发展趋势
CDP(Cloudera Data Platform)是Cloudera 和 HortonWorks 合并后推出的新一代大数据平台 ,并正在逐步停止对原有的大数据平台 CDH 和 HDP 的维护.笔记 ...
- ORA-600 [kkqjpdpvpd: no join pred found.]
场景 一个比较大的sql查询,报出了ORA-600 [kkqjpdpvpd: no join pred found.] 解决方法: 根据metalink提供的解决思路.当于当前session,执行如下 ...
- 启动docker某个image(镜像)的已经关闭的container(容器)
1.创建一个后台运行 ubuntu 容器 root@haima-PC:/home/haima/Desktop# docker run -d --name ubuntu-lnmp ubuntu bf24 ...
- 原生微信小程序button去掉边框
直接改没反应,需要使用::after更改
- 『手撕Vue-CLI』添加帮助和版本号
前言 经过上一篇『手撕Vue-CLI』编码规范检查之后,手撕 Vue-CLI 已经进阶到了代码规范检查这一步,已经将基本的工程搭建好了,然后代码规范约束也已经加入了,并且将 nue-cli 指令绑定到 ...
- mvc5接口报错:The JSON request was too large to be deserialized的一种原因
是mvc5版本的接口,接口使用了dynamic接收数组,json对象数组只有56个,length长度不到10万,但是提交就报The JSON request was too large to be d ...
- c++ 记一次把qrencode源码生成动态库的尝试
在网上搜二维码库:qrencode,源码下载:https://github.com/fukuchi/libqrencode 我的是windows环境,IDE是vs2022. 建立一个动态库的空工程. ...
- 在WPF中判断是是否为设计时模式
方式一: using System.ComponentModel; private bool IsInDesignMode { get { return DesignerPro ...
- Pyomo基础学习笔记:建模组成要素的编写方法
1.Pyomo 简介 pyomo文档[数学建模]优化模型建模语言 Pyomo 入门教程 - 知乎 (zhihu.com) Pyomo 是基于 Python 的开源软件包,主要功能是建立数学规划模型,包 ...