Subarray Sums I#11721

Subarray Sums I (Editorial)

Let's implement a sliding window using two pointers, and . For each fixed i = 1, 2, ..., expand the interval as much as possible so that the sum of its elements does not exceed . In other words, for each , search for the largest possible such that the sum of elements in the interval does not exceed , while the sum of elements in the interval [i ... j + 1] exceeds .

Let be the sum of numbers in the interval . If s + a[j + 1] \le m, expand the interval to [i ... j + 1]. Otherwise, shrink it to [i + 1 ... j]. Count the number of intervals with a sum of .

Example

Let's examine the movement of the pointers for the given example.

  1. i = 0, moves forward until the sum of the numbers in the interval exceeds x = 7. We stop at the interval , since the sum of the numbers in it is , while in the interval , the sum of the numbers is already .

  2. i = 1, moves forward to . The sum of the numbers in the interval is , while in the interval , it is already .

  3. i = 2, the considered interval is . The sum of the numbers in it is , but we cannot move the index forward because the sum of the numbers in the interval is , which is greater than x = 7.

  4. i = 3, the considered interval is . The sum of the numbers in it is , but we cannot move the index forward because the sum of the numbers in the interval is , which is greater than x = 7.

  5. i = 4, the considered interval is . The sum of the numbers in it is .

The number of subarrays with a sum of x = 7 is . They start at indices , and .

Algorithm realization

Declare an array.

#define MAX 200001
long long a[MAX];

Read the input data.

scanf("%d %lld", &n, &x);
for (i = 0; i < n; i++)
  scanf("%lld", &a[i]);

Initially, set the current interval [i ... j] = [0; 0]. The sum of the numbers in this interval is s = 0.

s = j = 0;

For each value of , sequentially process the intervals .

for (i = 0; i < n; i++)
{

For the fixed left end of the interval , search for the largest such that the sum of elements in this interval does not exceed .

  while ((j < n) && (s + a[j] <= x)) s += a[j++];

If the sum of the numbers in the current interval equals , increase the desired subarray count by .

  if (s == x) cnt++;

Recompute the sum for the interval [i + 1 ... j].

  s -= a[i];
}

Print the answer.

printf("%lld\n", cnt);