计数子阵列的总和在[L,R]范围内
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计数子阵列的总和在[L,R]范围内相关的知识,希望对你有一定的参考价值。
我正在解决竞争性编程问题,它被描述为:
给定n <10 ^ 5整数a1,a2,a3,...,an和L,R。有多少个子阵列,使得其元素之和在[L,R]范围内。
例:
输入:
n = 4, L = 2, R = 4
1 2 3 4
产量:4
(4 = 4, 3 = 1 + 2 = 3, 2 = 2)
我有一个解决方案是暴力,但是O(n ^ 2)太慢了。我应该使用哪些数据结构/算法来有效地解决这个问题?
答案
计算前缀和(p [0] = 0,p [1] = a1,p [2] = a1 + a2,...,p [n] =所有数字的总和)。
对于固定前缀sum p [i],您需要找到j小于i且p [i] - R <= p [j] <= p [i]的此类前缀和p [j]的数量 - L.可以使用treap或其他平衡二叉搜索树在O(log n)中执行此操作。
伪代码:
treap.add(0)
sum = 0
ans = 0
for i from 1 to n:
sum += a[i]
left, right = treap.split(sum - R)
middle, right = right.split(sum - L)
ans += middle.size()
merge left, middle and right together
treap.add(sum)
另一答案
如果数组只包含正数,我们可以在线性时间内完成。
首先从左到右构建一个前缀为sum的数组。
1. Fix three pointers, X, Y and Z and initialize them with 0
2. At every step increase X by 1
3. While sum of numbers between X and Y are greater than R keep increasing Y
4. While sum of numbers between X and Z are greater than or equal to L, keep increasing Z
5. If valid Y and Z are found, add Z - Y + 1 to result.
6. If X is less than length of the array, Go to step 2.
以上是关于计数子阵列的总和在[L,R]范围内的主要内容,如果未能解决你的问题,请参考以下文章
R语言计算时间窗口内的统计值(滑动平均滑动最大值滑动中位数滑动计数滑动总和等)实战
c_cpp 最大子阵列总和。在具有最大总和的数组(包含至少一个数字)中查找连续的子数组。