Редакция для Сумма на отрезке
Submitting an official solution before solving the problem yourself is a bannable offence.
Автор:
Разбор задачи «Сумма на отрезке»
1. Идея
Нужно много раз находить сумму на подотрезке массива: от l до r.
Если для каждого запроса просто складывать элементы от l до r, то один запрос может работать за O(n), а все запросы — за O(nq). При n, q до 2 * 10^5 это слишком медленно.
Поэтому нужно заранее подготовить вспомогательный массив, который позволит отвечать на каждый запрос за O(1).
Для этого используются префиксные суммы.
2. Наблюдения
Определим массив pref, где:
pref[0] = 0pref[i]— сумма первыхiэлементов массива
То есть:
pref[1] = a[1]pref[2] = a[1] + a[2]- ...
pref[i] = a[1] + a[2] + ... + a[i]
Тогда сумма на отрезке [l, r] равна:
pref[r] - pref[l - 1]
Почему это так:
pref[r]содержит сумму от1доrpref[l - 1]содержит сумму от1доl - 1- если вычесть второе из первого, останется сумма от
lдоr
Это и есть основной приём задачи.
3. Алгоритм
- Считываем
nиq. - Считываем массив из
nчисел. - Строим массив префиксных сумм
prefдлиныn + 1:pref[0] = 0- для
iот1доn:pref[i] = pref[i - 1] + a[i - 1]в Python- или читаем число сразу и записываем
pref[i] = pref[i - 1] + xв C++
- Для каждого запроса
(l, r)выводим:pref[r] - pref[l - 1]
4. Почему это работает
Докажем корректность.
Пусть:
pref[r] = a[1] + a[2] + ... + a[r]pref[l - 1] = a[1] + a[2] + ... + a[l - 1]
Тогда разность:
pref[r] - pref[l - 1]
равна:
(a[1] + ... + a[l - 1] + a[l] + ... + a[r]) - (a[1] + ... + a[l - 1])
Все слагаемые от a[1] до a[l - 1] сокращаются, остаётся:
a[l] + a[l + 1] + ... + a[r]
Это именно сумма на отрезке [l, r].
Значит, для каждого запроса формула даёт правильный ответ.
5. Сложность
Построение массива префиксных сумм:
O(n)
Обработка одного запроса:
O(1)
Обработка всех запросов:
O(q)
Итоговая сложность:
O(n + q)
Память:
O(n)
6. Код на C++17
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, q;
cin >> n >> q;
vector<long long> pref(n + 1, 0);
for (int i = 1; i <= n; i++) {
long long x;
cin >> x;
pref[i] = pref[i - 1] + x;
}
for (int i = 0; i < q; i++) {
int l, r;
cin >> l >> r;
cout << pref[r] - pref[l - 1] << '\n';
}
return 0;
}
7. Код на Python 3
n, q = map(int, input().split())
a = list(map(int, input().split()))
pref = [0] * (n + 1)
for i in range(1, n + 1):
pref[i] = pref[i - 1] + a[i - 1]
for _ in range(q):
l, r = map(int, input().split())
print(pref[r] - pref[l - 1])
Комментарии