线段树是一棵平衡二叉树,又是一棵排序二叉树。它的深度不超过log2L,区间上的任意一条线段被线段树分成不超过2log2L条线段。所以线段树能在O(log2L)的时间内完成一条线段的插入、删除、查找等操作。
一棵线段棵的结点所包含的基本信息包括:区间左、右边界B和E,区间覆盖次数C。 根据静态数组或动态指针等不同的实现方式,每个结点可能还要包括左、右儿子结果的地址字段。我个人倾向于用类似二叉堆的形式来存放线段树,因为父结点与子结点之间有一个简单的数学关系。
在利用线段树为工具设计算法时,往往还需要在结点中包含其它字段。对这些字段的维护时间复杂性,决定了算法的成败。我们说,一个字段的值对于线段树是可维护的,是指对该字段的任何操作(插入、删除、更新)都在O(log2L)的时间内完成。
点线段树是指叶结点的区间两端点相等的线段树。有时问题中的数量关系存在于区间中的整数“点”上,例如本题中在一段车站区间上的购票申请,其实是落实到具体的某些车站上车的人能否找到位置的问题。这种线段树在各个层次的相邻结点的区间端点是不相接的,前后相差1,否则就会存在重复计数问题。因此,在递归构建线段树时,指定左、右儿子的区间范围时,如果左儿子的右端点设为mid,那么右儿子的左端点则要设为mid+1。
售票系统这道题的思路还是很简单的。最直接的做法当前是开一个数组直接模拟,但查询一个区间能否接受本次购票申请的时间很长,每一次更新成功了的购票申请时的时间也很长。采用线段树的目的就是用尽可能少的查询次数就确定接受还是拒绝,以及以尽可能少的操作更新结点信息。