Разбор
Реализуем скользящее окно с помощью двух указателей и . Для каждого фиксированного будем по максимуму раздвигать интервал так, чтобы сумма элементов на нем была не больше . То есть для каждого ищем такое наибольшее значение , что сумма элементов на интервале не превышает , а сумма элементов на интервале уже больше .
Пусть — сумма чисел на интервале . Если , то расширяем интервал до . Иначе сокращаем его до . Подсчитываем количество интервалов с суммой .
Пример
Рассмотрим движение указателей для приведенного примера.
, движется вперед, пока сумма чисел на интервале не станет больше . Остановимся на интервале , так как сумма чисел на нем равна , а на интервале сумма чисел уже равна .
, двигаем вперед до . Сумма чисел на интервале равна , а на интервале уже .
, рассматриваемый интервал . Сумма чисел на нем равна , однако двигать индекс вперед мы не можем, потому что сумма чисел на интервале равна , что больше .
, рассматриваемый интервал . Сумма чисел на нем равна , однако двигать индекс вперед мы не можем, потому что сумма чисел на интервале равна , что больше .
, рассматриваемый интервал . Сумма чисел на нем равна .
Количество подмассивов с суммой равно . Они начинаются с индексов и .
Реализация алгоритма
Объявим рабочий массив.
#define MAX 200001 long long a[MAX];
Читаем входные данные.
scanf("%d %lld", &n, &x); for (i = 0; i < n; i++) scanf("%lld", &a[i]);
Изначально установим текущий интервал . Сумма чисел на этом интервале равна .
s = j = 0;
Для каждого значения последовательно обрабатываем интервалы .
for (i = 0; i < n; i++) {
Для фиксированного левого конца интервала ищем наибольшее , для которого сумма элементов на указанном интервале не превосходит .
while ((j < n) && (s + a[j] <= x)) s += a[j++];
Если сумма чисел на текущем интервале равна , то искомое количество подмассивов увеличиваем на .
if (s == x) cnt++;
Пересчитываем сумму чисел для интервала .
s -= a[i]; }
Выводим ответ.
printf("%lld\n", cnt);