块状链表
众所周知,数组可以以 \(O(1)\) 的复杂度查询、修改元素,但删除和插入元素的复杂度是 \(O(n)\) 的;链表恰好相反,插入、删除元素的复杂度为 \(O(1)\),但查询为 \(O(n)\)。
有没有能以较优复杂度完成插入、删除、查询、修改操作的线性数据结构?
本篇介绍的块状链表就可以。
顾名思义,块状链表运用分块的思想,将数组与链表结合起来。这里引用一张经典的图来展示它大概的样子:
可以看出块状链表就是以数组为节点(块)的链表。
例一
我们借P4008 [NOI2003] 文本编辑器这道题来理解块状链表的各个操作。
P4008 [NOI2003] 文本编辑器
维护一个字符串,支持在指定位置插入字符串、删除字符串、查询指定长度的连续字串。
内存分配
与正常的链表一样,块状链表中会出现很多新建、删除节点的操作,必须让被删除节点的位置能被新节点再次占用,否则会产生很多空节点,从而使内存巨大。为此我们使用作为内存池的栈 pool[]。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
合并
为了保证复杂度,需要同时限制块的总数与最大块长。一个很好的方法是,对于相邻的块,如果他们的长度和不超过最大块长,就将他们合并。

实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
分裂
在插入或删除元素时,需要将待操作位置单独分成块,再进行类似链表的插入、删除操作。

实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
具体操作
- 插入:将插入位置的块分裂,把待插入字符串分成长度不超过 \(mxsize\) 的块,依次插入。
- 删除:将要删除的左右端点的块分裂,删去中间所有块。
- 查询:将会被查到的所有块复制到答案字符串上。

实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
容易得出,当最大块长为 \(\sqrt n\) 时,插入、删除和查询的复杂度均为 \(O(\sqrt n+len)\)。
总体代码
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
例二
P3391 【模板】文艺平衡树
给定一个长度为 \(n\) 的序列 \(a\),初始 \(a_i=i\),执行多次区间翻转操作,求操作后序列。
将需要翻转的区间中的所有块顺序翻转,并给每一块打上翻转标记,在合并、分裂时检查标记。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
例三
P2596 [ZJOI2006] 书架
给定一个 \(1 \sim n\) 的排列,操作为将某个数放到最前面、放到最后面或向前、后移动一步,询问 \(s\) 位置的数或数 \(s\) 的位置。
这三种操作都可以视为从排列中删除一个数,再插入一个数。
这道题中比较麻烦的一点是,移动数的操作给定的都是数的值,因此可以给每一个块开一个桶 book[] 以记录其中是否包含某个数,进行移动操作之前先查询位置。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | |