计数子阵列的总和在[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]范围内的主要内容,如果未能解决你的问题,请参考以下文章

线段树--概念+模板+入门题

BZOJ - 3489 KD树 范围计数 空间思维转换

R语言计算时间窗口内的统计值(滑动平均滑动最大值滑动中位数滑动计数滑动总和等)实战

c_cpp 最大子阵列总和。在具有最大总和的数组(包含至少一个数字)中查找连续的子数组。

谷歌面试:在给定的整数数组中找到所有连续的子序列,其总和在给定范围内。我们能比 O(n^2) 做得更好吗?

javascript 给定总和的子阵列