常用数据结构简介
1.线段树简介
线段树是建立在线段基础上的,每个结点都代表了一条线段[a, b]。长度为1的线段称为元线段。非元线段都有两个子结点,左结点代表的线段为[a, (a + b) / 2],右结点代表的线段为[(a + b) / 2, b]。
线段树支持最基本的操作是插入和删除一条线段。下面以插入操作为例进行详细叙述,删除操作与之类似。
将一条线段[a, b]插入到代表线段[1, r]的结点p中,如果p不是元线段,那么令mid = (1 + r) / 2。如果a < mid, 那么将线段[a, b]插入到p的左儿子结点中;如果b > mid,那么将线段[a, b]插入到p的右儿子结点中。
插入(删除)操作的时间复杂度为O(log n)。
上面的都是些基本的线段树结构,但只有这些并不能做什么,就好比一个程序有输入没有输出,根本没有任何用处。
最简单的应用就是记录线段是否被覆盖,并随时查询当前覆盖线段的总长度。此时可以在结点结构中加入一个变量int count,代表当前结点代表的子树中被覆盖的线段长度和。这样就要在插入(删除)操作中维护这个count值,于是当前的覆盖总值就是根结点的count值了。
另外,也可以将count换成bool cover,支持查找一个结点或者线段是否被覆盖。
2. 并查集简介
并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。常常在使用中以森林来表示。
并查集的主要操作如下:
- 查找。查找元素所在的集合即根结点。
- 合并。将两个元素所在的集合合并为一个集合。
- 合并两个不相交集合判断两个元素是否属于同一集合。
3. 树状数组简介
树状数组是一个查询和修改复杂度都为log(n)的数据结构,假设有数组a[1…n],那么查询a[1] + ···+ a[n] 的时间为log(n)级别。而且,树状数组是一个在线的数据结构,支持随时修改某个元素的值,修改操作的复杂度也为log(n)级别。