Префиксные суммы

Один раз считаем накопленные суммы от начала. Тогда сумма любого отрезка — это разность двух готовых чисел, и складывать отрезок заново не нужно.

Вариант
P04 Префиксные суммыСумма подмассива · 1×

Пример задачи: посчитать подмассивы [2, -1, 1, 5, 2, 2, 3] с суммой 7.

numsprefix2-115223
ещё не дошлиуже пройденотекущеепрошлый префикс, равный needподмассив с суммой k

Пока ничего не нашли: count = 0

count = 0prefix = –seen = –x = –need = –
01/42
сначала · назад · пуск · шаг
Скорость
1function countSubarrays(nums, k):
2 count = 0
3 prefix = 0
4 seen = map {0: 1} // missing keys: 0
5 for each x in nums:
6 prefix = prefix + x
7 need = prefix - k
8 if need in seen:
9 count = count + seen[need]
10 seen[prefix] = seen[prefix] + 1
11 return count

← → шаг · пробел — пауза

Как узнать

сумма непрерывного отрезка: сколько подмассивов дают k, много вопросов о сумме от i до j или отрицательные числа, из-за которых не работает скользящее окно.

Как решать такие задачи

  1. Перепиши сумму отрезка как разность двух накопленных сумм.
  2. Реши, что помнить о прошлых префиксах: сколько раз встречался, первый индекс или только сам факт.
  3. Сначала положи в словарь пустой префикс 0, чтобы считались и отрезки от начала.
  4. Для каждого числа: обнови сумму, поищи нужный префикс, потом сохрани текущий.

Вариант: С двух сторон

То же, но накапливаем с двух сторон: один проход слева, другой справа. Подходит, когда ответ для позиции зависит от всего, что слева от неё, и всего, что справа.

  1. Подходит, когда ответ для i зависит от всего, что левее i, и от всего, что правее.
  2. Пройди слева и сохрани для каждого индекса то, что перед ним: произведение, сумму, максимум.
  3. Пройди справа с одной накопленной величиной для того, что после него, и объедини с сохранённым.
  4. Те же два прохода дают самую высокую стенку слева и справа от каждой клетки, когда считаешь, сколько дождевой воды задержится, и решают правило с двумя соседями: раздать конфеты так, чтобы рейтинг выше давал больше, чем у обоих соседей.

Где встречается

  • Поиск лиц на фото. Детектор Виолы — Джонса, который есть в OpenCV, много раз считает сумму яркости в прямоугольниках. Для этого он заранее строит таблицу накопленных сумм, и сумма любого прямоугольника берётся из четырёх её чисел.
  • Сортировка на видеокарте. Radix sort считает, сколько чисел попало в каждую корзину, а накопленные суммы этих счётчиков говорят, с какого места писать каждую корзину. Так сортирует библиотека CUB от NVIDIA.
  • SQL. Оконная функция SUM(...) OVER (ORDER BY ...) считает нарастающий итог: для каждой строки сумму всех строк до неё. Это и есть накопленные суммы.