计数子阵列的总和在[L,R]范围内

时间:2014-08-04 14:41:21

标签: algorithm data-structures

我正在解决竞争性编程问题,它的描述如下:

  

给定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)太慢了。我应该使用哪些数据结构/算法来有效地解决这个问题?

2 个答案:

答案 0 :(得分:3)

计算前缀和(p [0] = 0,p [1] = a1,p [2] = a1 + a2,...,p [n] =所有数字的总和)。

对于固定前缀sum p [i],您需要找到j小于i且p [i] -R <= p [j] <=的这种前缀和p [j]的数量p [i] - 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)

答案 1 :(得分:2)

如果数组只包含正数,我们可以在线性时间内完成。

首先从左到右构建一个前缀为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.