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板子 - 维护一个分裂和合并的序列的更多相关文章

  1. 模板——伸展树 splay 实现快速分裂合并的序列

    伸展操作:将treap中特定的结点旋转到根 //将序列中从左数第k个元素伸展到根,注意结点键值保存的是原序列id void splay(Node* &o, int k) { ] == NULL ...

  2. [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  3. POJ - 3481 splay板子

    Double Queue 默写splay板子 很多细节问题... #include<cstdio> #include<iostream> using namespace std ...

  4. 区间树Splay——[NOI2005]维护数列

    无指针Splay超详细讲解 区间树这玩意真TM玄学. 学这东西你必须要拥有的 1.通过[模板]文艺平衡树(Splay),[模板]普通平衡树,GSS3 - Can you answer these qu ...

  5. BST,Splay平衡树学习笔记

    BST,Splay平衡树学习笔记 1.二叉查找树BST BST是一种二叉树形结构,其特点就在于:每一个非叶子结点的值都大于他的左子树中的任意一个值,并都小于他的右子树中的任意一个值. 2.BST的用处 ...

  6. Java中使用IO流实现大文件的分裂与合并

    文件分割应该算一个比较实用的功能,举例子说明吧比如说:你有一个3G的文件要从一台电脑Copy到另一台电脑, 但是你的存储设备(比如SD卡)只有1G ,这个时候就可以把这个文件切割成3个1G的文件 ,分 ...

  7. [bzoj] 1588 营业额统计 || Splay板子题

    原题 给出一个n个数的数列ai ,对于第i个元素ai定义\(fi=min(|ai-aj|) (1<=j<i)\),f1=a1,求\(/sumfi\) Splay板子题. Splay讲解:h ...

  8. BZOJ 3224 Tyvj 1728 普通平衡树 | Splay 板子+SPlay详细讲解

    下面给出Splay的实现方法(复杂度证明什么的知道是 nlogn 就可以啦) 首先对于一颗可爱的二叉查找树,是不能保证最坏nlogn的复杂度(可以想象把一个升序序列插入) (二叉查找树保证左子树元素大 ...

  9. BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)

    BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...

  10. HDU 5945 维护一个单调队列 dp

    Fxx and game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Tot ...

随机推荐

  1. 2019-11-29-VisualStudio-2019-如何离线下载

    title author date CreateTime categories VisualStudio 2019 如何离线下载 lindexi 2019-11-29 08:38:13 +0800 2 ...

  2. 国内常用源开发环境换源(flutter换源,python换源,Linux换源,npm换源)

    国内开源镜像站点 大学 清华大学开源软件镜像站 (使用较多) 中国科学技术大学开源软件镜像 (使用较多) 浙江大学开源镜像站 (主要是各发行版Linux,pip等常用库) 哈尔滨工业大学开源镜像站 ( ...

  3. .NET开源、功能强大、跨平台的图表库 - LiveCharts2

    前言 今天大姚给大家分享一个.NET开源(MIT License).功能强大.简单.灵活.跨平台的图表.地图和仪表库:LiveCharts2.   项目介绍 LiveCharts2是一个.NET开源. ...

  4. element-ui使用el-date-picker日期组件常见场景

    开始 最近一直在使用 element-ui中的日期组件. 所以想对日期组件常用的做一个简单的总结: 1.处理日期组件选择的时候面板联动问题 2.限制时间范围 解除两个日期面板之间的联动 我们发现2个日 ...

  5. windows server2012 挂载linux的nfs共享目录

    1.安装NFS客户端 首先win-server上添加角色-----选择文件服务-----网络文件系统(或者NFS客户端)-安装 2.挂载nfs目录 先cmd检查服务端的共享目录 然后执行:showmo ...

  6. 每天上一当系列之vue修饰符.number

    今天使用number修饰符去处理el-input的内容为数字做校验原本以为省事不少,没想到,为0开头无法输入第二位以后,并且输入的比较多的时候会出现Infinity 很神奇,网上查了说是element ...

  7. 阿克曼函数(Ackermann function)部分推导

    相关题目 已知\(Ackermann function\)为 \[Ack(m,n)=\begin{cases}n+1(m=0) \\ Ack(m-1,1)(m>0,n=0) \\ Ack(m-1 ...

  8. 80x86汇编—80x86架构

    文章目录 计算机如何工作 存储器 逻辑地址到物理地址 寄存器 数据寄存器使用细节 其他知识点细节 堆栈Stack 标志寄存器 中断 汇编入门简单,深入难 使用8086架构进行学习,本章节如果没有学过计 ...

  9. Springboot+Mybatis+Clickhouse+jsp 搭建单体应用项目(二)(添加日志打印和源码地址)

    一.添加yaml设置 1 logging: 2 level: 3 com.mrliu.undertow.mapper : debug 二.添加pom的Hutool工具,完善日志打印处理 1 <d ...

  10. apisix~集成服务发现注册中心

    摘要 当业务量发生变化时,需要对上游服务进行扩缩容,或者因服务器硬件故障需要更换服务器.如果网关是通过配置来维护上游服务信息,在微服务架构模式下,其带来的维护成本可想而知.再者因不能及时更新这些信息, ...