dataStructure_SegmentTree - 线段树
1 线段树原理
1.1 数组实现
1.2 线段树树形实现
1 | class SegTree { |
0327. 区间和的个数
1 题目
https://leetcode-cn.com/problems/count-of-range-sum/
题和逆序数对的计算方式相同:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
就是做了一个小改变而已,很多统计区间值的,st-ed < tar, 本来是让你找一个st,ed的对子的,那么就会转换思路为:
对于每一个ed找st,什么样的呢? st < ed + tar
然后找这样的st就有很多方法,比如hash,前缀和,bitree,priority_queue
2 解题思路
- 1 求逆序对的思路:
- 1.1 首先注意到:对于数组{5,5,2,3,6}而言,得到每个value的个数的统计:
- index -> 1 2 3 4 5 6 7 8 9
- value -> 0 1 1 0 2 1 0 0 0
- 1.2 那么上述过程中,比如对于5,其贡献的逆序数对为5之前所有数字出现次数的和,也就是value数组中2之前的前缀和!
- 1.1 首先注意到:对于数组{5,5,2,3,6}而言,得到每个value的个数的统计:
- 2 那么如何快速获得前缀和呢?考虑使用BST来获取,参考:https://xychen5.github.io/2021/12/15/dataStructure-BinaryIndexedTree/
- 2.1 整体思路如下:
- a 使用数字在数组中的排名来代替数字(这不会对逆序数对的个数产生影响)
- b 对数组nums中的元素nums[i]从右到左构建BITree(i 从 n-1 到 0),注意,BITree所对应的前缀和是数组里数字出现次数的和
- 比如进行到nums[i],那么nums[i]右边的数字都已经统计了他们的出现次数,而后获取nums[i] - 1的前缀和,即可获取所有 < nums[i]的数字在nums[i:n]中的出现次数之和,也就是nums[i]贡献的逆序数对的个数
- 之所以是逆序遍历构建BITree,是因为对于nums[i],它能够贡献的逆序数对的个数仅仅出现在它的右侧,所以需要在右侧进行
- 2.2 额外说一下数组离散化,也就是不关系数字大小本身,只关心他们之间的相对排位
- 2.1 整体思路如下:
- 3 使用线段树解题
1 | class Solution { |
5 可能发生的问题
注意其中很重要的一点:
对于线段树中插入一个节点时,需要对沿路所有节点的sum加上要插入的节点的值,找这个节点位置的时候,
需要找到root左右管辖范围的中间值mid,此时务必使用>>1去做,因为获得mid我们要求其为 floor(left + right),
(cpp和python对于移位和除法的逻辑是相同的),这里就显示出了2者的区别,
当然在数字都为正数的时候不会出错!
1 | int((-1 + 0) / 2) |