思路讲解
树状数组经典题。
然后前面看半天看不太懂,原来是用了频数数组呀,我想为啥要用树状数组那?
原来数组里维护的是频数,需要区间查询+单点修改两个操作,这个树状数组操作我还是会的。
频数数组
很多数据结构都是基于「频数数组」。
给定数组 t 以及它的下标范围 [L,R],t[x] 就表示元素 x 在数据结构中的出现次数。基于此,上述的两个操作可以变为:
操作 1「查询」:给定一个范围 [left,right],查询 t[left] 到 t[right] 的和;
操作 2「更新」:给定一个元素 x,将 t[x] 增加 1。
这也是线段树和树状数组的基础,它们需要的空间都与数组 t 的下标范围 [L,R] 正相关。在本题数据规模较大的情况下(例如测试数据中,出现了元素值达到 32 位有符号整数的上下界),线段树和树状数组都会超出空间限制,因此需要借助「离散化」操作,将这些元素映射到一个较小规模的区间内。
https://leetcode.cn/problems/count-of-range-sum/solutions/476205/xian-ren-zhi-lu-ru-he-xue-xi-ke-yi-jie-jue-ben-ti-/
AC代码
https://leetcode.cn/problems/count-of-range-sum/submissions/585372478/
1 | class Solution { |
心路历程(WA,TLE,MLE……)
唉这题搞了半天
记住,离散化之后,传入的数组大小应该是去重以后的大小(即ditinctN),否则搜出lii的递增范围,lower_bound()就不可靠了。
1 | search(sumA[i]-upper,sumA[i]-lower,BIT,lii,distinctN); |
https://leetcode.cn/problems/count-of-range-sum/submissions/585369029/
记得离散化映射关系数组的初始化值为0容易出事,因为如果是搜0,搜到外面去容易出事
1 | vector<ll> lii(n+10,-1e11+7);// 离散化映射关系数组 |