描述
给一个数组nums
, 和一些query(连续到来). 每个query都是[l, r]
的格式(闭区间左右端点). 对于每个query, 求出在这个区间内的数中, 出现次数等于本身值的数的个数. 比如[2,2,3,3,3]
, 2
出现了2
次, 3
出现了3
次, 那么结果是1+1=2
.
数组长度和query个数各自都是最大100000
.
思路
并没有什么思路, 用线段树可解但是判断条件太复杂了…
不妨思考一下暴力解, 普通的暴力解就是每个query都统计一下那个区间内的数字和对应的频数. 这样复杂度是O(n**2)
, 肯定过不了OJ. 然后思考query规则, 对于数字x
, 她需要出现x
次, 那么对于长度最大100000
的数组, 如果整体query([0, length]
)的话, 最大可能的返回值是多少呢?1(1个1, 不能更多了, 否则会浪费名额, 相当于降低100000这个最大值) + 2(2个2) + 3 + ... + n <= 100000
, n
最大446
左右. 对于446*100000
的复杂度, 勉强可以接受.
所以我们可以枚举所有在nums
中的数字, 只有当前数字自身比它出现次数小时(反之, 在任何一个小区间也不可能x == count[x]
), 计算一下它的次数前缀和, 然后对于所有query, 计算这个数字对每个query的贡献.
因为不是实时处理query而是集中处理, 集中返回答案, 属于离线算法.
代码
1 | import collections |