线段树是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶子节点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。
对于线段树中每一个非叶子节点(即长度大于单位长度)[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b],因此线段树是平衡二叉树。
最简单的应用就是记录线段是否被覆盖
树状数组
最下面一行为原来的数组A,红色为树状数组C
则
- C[1] = A[1]
- C[2] = A[1] + A[2]
- C[3] = A[3]
- C[4] = A[1] + A[2] + A[3] + A[4]
- C[5] = A[5]
- C[6] = A[5] + A[6]
- C[7] = A[7]
- C[8] = A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]
高效计算数列的前缀和,区间和
求逆序数
逆序数是一个数列中在它前面有比它大的个数,如521的逆序数是0+1+2=3
从最后一个数开始遍历,每次在树状数组中查询有多少个数小于当前的数并加入计数器,之后把当前元素加入树状数组