Сумма на квартале
Условие
В городе сетка кварталов размера H×W. В каждом квартале записано число — насколько там “шумно” сегодня (может быть отрицательным: значит, там стало тише).
Мэрия задаёт много вопросов вида: «Каков общий шум на прямоугольном районе?» Район всегда задаётся двумя углами и включает все кварталы внутри.
Важно: сумма по району может не помещаться в 32-битный тип (как на некоторых языках), ориентируйтесь на 64-битные значения. В Python это не проблема.
Формат ввода
Первая строка: два целых числа H и W (1 ≤ H ≤ 250, 1 ≤ W ≤ 250). Далее H строк по W целых чисел a[i][j] (−10^6 ≤ a[i][j] ≤ 10^6). Затем целое число Q (1 ≤ Q ≤ 4000). Далее Q строк: r1 c1 r2 c2 — координаты прямоугольника (1 ≤ r1 ≤ r2 ≤ H, 1 ≤ c1 ≤ c2 ≤ W). Прямоугольник включает все клетки с строками от r1 до r2 и столбцами от c1 до c2.
Формат вывода
Выведите Q строк. В i-й строке — сумму чисел в указанном прямоугольнике.
Ограничения
H, W ≤ 250, Q ≤ 4000. Значения в клетках от −10^6 до 10^6.
Пример
Ввод:
3 4
1 2 3 4
-5 0 7 1
2 2 2 2
2
1 1 2 3
2 2 3 4
Вывод:
8
14Как решать — идея подхода
Приём: 2D префиксные суммы
Ключевое наблюдение: если уметь быстро находить сумму в прямоугольнике от (1,1) до (r,c), то любой запросный прямоугольник можно собрать из четырёх таких сумм (принцип «включил-исключил»).
Приём: 2D префиксные суммы. Строим таблицу ps, где ps[r][c] — сумма всех клеток в прямоугольнике с углами (1,1) и (r,c). Тогда сумма любого района (r1..r2, c1..c2) считается за константное время.
План решения:
- Создай
psразмером (H+1)×(W+1), заполни нулями (дополнительная нулевая строка и столбец упрощают границы). - Пройди по клеткам (r=1..H, c=1..W) и посчитай префиксы. Удобная формула:
ps[r][c] = ps[r-1][c] + ps[r][c-1] - ps[r-1][c-1] + a[r][c]
(можно ускорить, накапливая сумму по строке).
- Для каждого запроса используй включение-исключение:
sum = ps[r2][c2] - ps[r1-1][c2] - ps[r2][c1-1] + ps[r1-1][c1-1]- Выведи ответы.
Сложность: построение O(H*W), каждый запрос O(1), всего O(H*W + Q) по времени и O(H*W) по памяти.
Частая ошибка: перепутать знаки в формуле запроса или забыть сделать ps с «нулевой рамкой», из-за чего ломаются случаи с r1=1 или c1=1.
Разберись руками
Есть таблица 3×4 с “шумом” по кварталам. Приходят запросы: найти сумму чисел внутри прямоугольника, заданного двумя углами. На примере попробуем руками понять, как отвечать на запросы без пересчёта всех клеток каждый раз.
- Разомнёмся на 1-й строке: 1 2 3 4. Посчитай нарастающую сумму слева направо (после каждого добавления).
- Теперь так же посчитай нарастающую сумму по 1-му столбцу сверху вниз: 1, -5, 2.
- Посчитай сумму всех 12 клеток (всего прямоугольника 3×4). Это будет сумма “от (1,1) до правого нижнего угла (3,4)”.
- Запрос 2 из примера: прямоугольник (2,2)–(3,4). Представь, что у тебя уже есть суммы: - всего поля (1..3,1..4) = 21 - верхней полосы (1..1,1..4) = 10 - левой полосы (1..3,1..1) = -2 - их пересечения (1..1,1..1) = 1 Какое выражение даст сумму нужного прямоугольника (2..3,2..4)?
Идея: Сначала заранее посчитать для каждого угла сумму всего прямоугольника от (1,1) до этого угла. Тогда сумму любого прямоугольника можно получить из нескольких таких “угловых” сумм: берём большой прямоугольник, вычитаем лишнее сверху и слева, а то, что вычлось дважды, добавляем обратно.
Решить задачу с автопроверкой на Python →
Куда дальше
- Школьный этап ВсОШ по информатике — как устроен первый этап и план подготовки за четыре недели
- Родителям: подготовка бесплатно — сколько стоит репетитор, что даёт бесплатный маршрут и как понять, что ребёнок занимается
- БВИ и льготы при поступлении — какой диплом что даёт и сколько лет он действует