前言
众所周知,对于一个一维的数组,或是一个字符串,我们可以使用两种办法:数组或链表两种方法来储存。但是,看了国家集训队2008年苏煜的论文之后,就知道了一种神奇的骗分方式:数组+链表形成的块状链表。
先来看看块状链表和两种方式的对比
方式 | 修改 | 查询 |
---|---|---|
链表 | O(N) | O(1) |
数组 | O(1) | O(N) |
块状链表 | O(N−−√) | O(N−−√) |
显而易见,块状链表对于处理综合修改和查询的速度比单一的数组或链表都要快,当数据量很大的时候,就可以考虑用块状链表来骗分。
原理
块状链表的原理其实很简单。既然链表或是数组都不够快,就把它们拼在一起吧……
将一个链表中的每一个元素都换成一个数组,或者说将多个元素压缩在一起,变成一个数组。
如下图所示
但是,这并不是这么简单的,在操作的过程中需要进行几种的操作。
1.定位
定位也就是直接找点,找到点所在的块,再在这个块中寻找
2.分裂
将一个分块以指定的位置为中心,分成两个分块
3.合并
将两个分块合并为一个分块
4.插入
先将插入的位置分裂,然后将要插入的元素(分块)插入
5.删除
在删除部分的左右两端分裂,把这个部分分裂出来,再删除掉。
分析
先来分析一下为什么要做分裂和删除。
分裂是插入和删除必不可少的一部分。但在有些情况也需要分裂, 避免让块状数组退化成一般的数组。也就是所有的分块都在一起,成为了一个数组。
合并则正好相反,如果执行插入和删除过多,就会出现大量的分块,就可能退化为一般的链表。
综合这几步,就可以实现块状链表了。
如果还不明白,可以看看下面的两幅图:
1.插入
2.删除
总结
其实块状链表就是一种暴力的优化,属于骗分的范畴……
不过对于一部分的题目来说,块状链表可能是正解,或者正解太麻烦而块状链表刚好能够解决。
虽然看上去很简单,理解起来也简单,但实际实现却有些麻烦