块状链表(STL rope)
块状链表(STL rope)
首先介绍一下块状链表。
我们都知道:
数组 具有 O(1)的查询时间,O(N)的删除,O(N)的插入。
链表 具有 O(N)的查询时间,O(1)的删除,O(1)的插入。
既然数组和链表各有优劣,那么我们为何不将链表和数组组合起来,一起来均摊时间呢?
做法就是维护一个链表,链表中的每个单元包含一段数组,以及这个数组中的数据个数。每个链表中的数据连起来就是整个数据。
- 时间复杂度证明:
设链表的长度为a,每个单元中数组的长度为b。那么无论是插入还是删除,在寻址的时候都要遍历整个链表,复杂度是O(a);
对于插入操作,如果直接在链表中加入一个新的单元,时间复杂度是O(1),如果要在一个单元内插入一个新的数,那么则需要移动数组中的数据,复杂度是O(b),总的复杂度是O(a + b)。
对于删除操作,可能会涉及多个连续的单元,如果一个单元中的所有数据均要删除,直接删除这个单元,复杂度是O(1),如果只删除部分的数据,则要移动数组中的数据,复杂度是O(b)。总的复杂度是O(a + b)。
因为ab = n,取a = b = √n,则总的复杂度是O(2√n)= O(√n)。
问题是如何维护a和b大致等于√n?
插入操作:
每个链表节点的数据是一个数组块,那么问题来了,我们是根据什么将数组切开呢?总不能将所有的数据都放在一个链表的节点吧,那就退化成数组了。在理想的情况下,为了保持√N的数组个数,所以我们定了一个界限2√N,当链表中的节点数组的个数超过2√N的时候,当下次插入数据的时候,我们有两种做法:
① 在元素的数组插入处,将当前数组切开,插入元素处之前为一个链表节点,插入元素后为一个链表节点。
② 将元素插入数组后,将数组从中间位置切开。
删除操作:
跟插入道理一样,既然有裂开,就有合并,我们同样定义一个界限值√n/2,当链表节点的数组个数小于这个界限值的时候,就需要将此节点和后面的链表节点进行合并。
执行上述维护操作需要移动数组中的数据,复杂度是O(b),对于单元的分割和合并均是O(1)的,总的复杂度是O(b)的。这样,维护操作并不会使总复杂度增加。最终得到一个复杂度是O(√n)的数据结构。
因为块状链表的代码太过于冗长,所以如果实在要用到的话我推荐使用STL库里的rope(C++11及以上可使用),相关的rope讲解:
Rope大法(可持久化平衡树)
【可持久化线段树?!】rope史上最全详解
这里注意rope是支持"+"操作的。
题目
问题很简单,但是需要涉及到区间的操作,用rope暴力就行。复杂度为O(n√n)。
#include<bits/stdc++.h>
#include <ext/rope>
#define ll long long
#define inf 0x3f3f3f3f
#define endl '\n'
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)using namespace std;
using namespace __gnu_cxx;const int N = 1e5 + 10;rope<int>r;
int n, m, a, b;int main()
{scanf("%d%d", &n, &m);for(int i = 1; i <= n; i ++) r.push_back(i);while(m --){scanf("%d%d", &a, &b);r = r.substr(a - 1, b) + r.substr(0, a - 1) + r.substr(a + b - 1, n - a - b + 1); // -1是因为rope的下标从0开始}for(int i = 0; i < n; i ++)printf("%d ", r[i]);return 0;
}
块状链表(STL rope)相关推荐
- Splay ---- 2018牛客多校第三场 区间翻转搞区间位移 或者 rope可持久化块状链表
题目链接 题目大意: 就是每次把牌堆中若干个连续的牌放到堆顶,问你最后牌的序列. 解题思路: Splay 区间翻转的模板题: 对于一个区间[1,2,3,4,5,6,7,8][1,2,3,4,5,6,7 ...
- c++ STL rope小结
rope是stl封装好的可持久平衡树(不支持kth). 基本操作(函数)比较少. 下标从0开始. {1,2,5,4}.insert(1,10)=>{1,10,2,5,4} #include< ...
- 【Splay】【块状链表】bzoj3223 Tyvj 1729 文艺平衡树
让蒟蒻见识到了常数大+滥用STL的危害. <法一>很久之前的Splay #include<cstdio> #include<algorithm> using nam ...
- [BZOJ3337] ORZJRY I --块状链表大毒瘤
link 题目大意:维护一个序列 支持: 1.单点插入 2.单点删除 3.区间翻转 4.区间旋转 5.区间加 6.区间赋值 7.询问区间和 8.询问区间极差 9.询问区间与给定某个数差值绝对值的最小值 ...
- 【POJ2887】Big String(块状链表,模板)
problem 给一个字符串,长度不超过 1e6,有两种操作: 在第 i 个字符的前面添加一个字符 ch 查询第 k 个位置是什么字符 操作的总数不超过 2000 solution 1.传统的数组所有 ...
- Python数据结构与算法(附录)——块状链表的动态调整
Python数据结构与算法(附录)--块状链表的动态调整 块状链表的动态调整 违反规则 1 违反规则 2 相关链接 块状链表的动态调整 我们已经知道块状链表的块的最大容量会随着链表长度的变化动态改变, ...
- 【数据结构与算法】 01 链表 (单链表、双向链表、循环链表、块状链表、头结点、链表反转与排序、约瑟夫环问题)
一.线性表 1.1 概念与特点 1.2 线性表的存储结构 1.3 常见操作 1.4 应用场景 二.链表 2.1 链表简介 2.2 单向链表(单链表) 2.21 基本概念 2.22 单链表基本操作 2. ...
- Python数据结构与算法(2.6)——块状链表
Python数据结构与算法(2.6)--块状链表 0. 学习目标 1. 块状链表简介 1.1 块状链表介绍 1.2 块状链表中结点类 1.3 块状链表中块类 2. 块状链表的实现 2.1 块状链表的初 ...
- 块状链表(附NOI 2003 Editor,POJ 2131 Key Insertion)
这两天学习了一下块状链表,也谈不上学习,可以说是练习.因为块状链表这种东西,猛一听起来好像很高端,但是拆开来说就是:分块+链表.根本上就是暴力,就是分块.只不过"分"的对象从数组变 ...
最新文章
- AI大潮来袭,Python将纳入高考?!你怎么看
- 定时器php windows任务计划
- android11 rom,小米打造基于安卓11的ROM来了:米10尝鲜
- 给linux默认mysql设置root密码
- 关于List转Json的简单方法
- 思科模拟器Cisco Packet Tracer的中文安装 [含安装包]
- 基于微信小程序评选投票系统 开题报告
- C# 生成word文件 小学一年级口算题生成器(代码)
- python ffmpeg mp3文件转为wav文件
- bugku never_give_up file_get_contents()有php://input漏洞 eregi \x00绕过
- elasticsearch创建索引和mapping
- 水库欧神评论雄安新区房产:999年358天
- 跨境电商面临“寒冬”考验,如何转型升级入局新赛道(Starday)
- oracle 闩锁(latch)概述
- ATMel的AT89C52芯片慎选
- 进销存设计中的库存设计
- 一款恋爱星座男女配对微信小程序源码
- 基于51单片机的DS1302实时时钟程序
- 阿里云云原生数据湖体系全解读——数据湖 云原生计算引擎
- 计算机从一级到四级要学多久,从一级到四级 全国计算机等级考试全攻略
热门文章
- ZigBee芯片CC2430/CC2530对比一览表
- 水果店的前景,开水果店前景
- C语言位图图像文件缩放(西电C程序作业3)
- [激光原理与应用-29]:典型激光器 -1- 固体激光器
- mysql关于菜单权限的设计_管理系统之权限的设计和实现
- 信息学奥赛一本通-2073:【例2.16 】三角形面积
- SAS中国用户大会:大数据的价值在于分析
- 【数学建模】线性规划模型基本原理与案例分享
- “清华大学出版社抄袭事件”——章忆文给我的短信
- cpp map 获取所有 key_久一英语,6-8月雅思口语题库-Part 1-Map