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 ...
随机推荐
- 在线程中使用Spring的Bean的方法、不推荐把“线程”注入到Spring
一.不推荐把"线程"注入到spring 将线程注入到Spring容器中并不是一个常见的做法,而且通常也不推荐这样做,原因如下: 生命周期管理困难: Spring管理的Bean生命周 ...
- ABAP 7.58 中支持任意精度算术的新类
1. 引言 通常,有两种对编程语言的改进.第一种是让困难的事情变得简单,第二种是让不可能的事情变为可能.本文介绍的是任意精度算术,它属于第二类:使在ABAP中原本不可能的事情成为可能. 过去已经可以在 ...
- 微信小程序使用微信云托管添加自定义域名并转发到pexels.com
背景:我要在小程序上显示pexels.com上的图片,然后我得先把pexels.com的域名添加到小程序的request合法域名中,但是pexels.com是国外的,在国内没有备案所以添加不了.解决方 ...
- postgresql 主键id配序列
一.手动创建序列 1.表格id字段,设置主键(PRIMARY KEY),类型为int4 2.创建序列 CREATE SEQUENCE public.moni_wzhour_warn_id_seq IN ...
- 一次glide内存泄漏排查分析
glide是一款非常优秀的图片加载框架,目前很多项目在使用.提供了非常方法,在此,笔者就不一一列举了,可以到官网查找. 目前项目在做内存排查,因为是车机项目,之前开发的时候没有注意内存方面的问题(车机 ...
- 效率工具mysoV0.3.0功能介绍
也许大家在日常工作中,有使用过提升效率的工具,比如快速搜索文件的Everything:火柴:Listary等,这些工具都在一定程度上提升您的工作效率.myso作为后来者,跟上述软件一样,也是为提升 ...
- Visual Studio中的四款代码格式化工具
前言 今天大姚给大家分享四款Visual Studio中的代码格式化工具.扩展插件.大家可以在Visual Studio中的管理扩展或者插件市场下载安装. 代码格式化工具的作用 自动调整代码的布局和风 ...
- Python:conda install 和pip install的区别
pip是个安装包的软件,conda是个环境管理的工具.conda能够安装多个python解释器,pip不行.因此conda在实际开发中是主要用来隔离不同的python版本和Tensorflow& ...
- 使用 TortoiseGit 时,报 Access denied 错误
当输入正确的密码时,总是报如下错误: 解决方法: 然后弹出如下对话框: 然后编辑本地配置文件: 然后将红色框的SSH配置改为绿色框的 HTTP配置,点击保存,确定. 然后再进行拉取源码,先输入用户名, ...
- 研二学妹面试字节,竟倒在了ThreadLocal上,这是不要应届生还是不要女生啊?
一.写在开头 今天和一个之前研二的学妹聊天,聊及她上周面试字节的情况,着实感受到了Java后端现在找工作的压力啊,记得在18,19年的时候,研究生计算机专业的学生,背背八股文找个Java开发工 ...