Редакция для Среднее на отрезке


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

1. Идея

Нужно найти среднюю температуру на отрезке дней от l до r.

Среднее значение на отрезке считается так:

  • сначала находим сумму всех температур с l по r,
  • затем делим эту сумму на количество дней r - l + 1.

Так как в условии прямо требуется использовать префиксные суммы, будем считать сумму отрезка через них.

Префиксная сумма pref[i] — это сумма первых i элементов массива. Тогда сумма на отрезке [l, r] равна:

pref[r] - pref[l - 1]

После этого остаётся только разделить на длину отрезка.

2. Наблюдения

  1. Если считать сумму от l до r обычным циклом, это тоже сработает, но в задаче требуется использовать префиксные суммы.

  2. Префиксный массив удобно делать длины n + 1, где:

    • pref[0] = 0,
    • pref[1] = a_1,
    • pref[2] = a_1 + a_2,
    • и так далее.
  3. Тогда формула суммы отрезка работает очень просто:

    • сумма 1..r — это pref[r],
    • сумма 1..(l-1) — это pref[l-1],
    • значит сумма l..r — это разность pref[r] - pref[l-1].
  4. Значения a_i могут быть большими по модулю, до 10^9, а n до 2 * 10^5, поэтому сумма может быть порядка 2 * 10^14.
    Значит, в C++ нужно использовать тип long long.

  5. Ответ может быть нецелым, поэтому выводить его нужно как вещественное число.

3. Алгоритм

  1. Считать число n.
  2. Считать массив температур.
  3. Построить массив префиксных сумм pref:
    • pref[0] = 0,
    • для каждого i от 1 до n:
      • pref[i] = pref[i - 1] + a[i - 1] в Python,
      • или считывать число сразу и обновлять pref[i] в C++.
  4. Считать l и r.
  5. Найти сумму на отрезке:
    • sum = pref[r] - pref[l - 1]
  6. Найти длину отрезка:
    • len = r - l + 1
  7. Найти среднее:
    • ans = sum / len
  8. Вывести ответ с точностью 6 знаков после запятой.

4. Почему это работает

По определению префиксной суммы:

  • pref[r] хранит сумму элементов от 1 до r,
  • pref[l - 1] хранит сумму элементов от 1 до l - 1.

Если из суммы первых r элементов вычесть сумму первых l - 1 элементов, останется только сумма элементов от l до r.

То есть:

  • pref[r] = a_1 + a_2 + ... + a_r
  • pref[l - 1] = a_1 + a_2 + ... + a_(l-1)

После вычитания получаем:

  • pref[r] - pref[l - 1] = a_l + a_(l+1) + ... + a_r

Это и есть сумма на нужном отрезке.

Дальше среднее значение по определению равно сумме элементов, делённой на их количество. Количество дней на отрезке [l, r] равно r - l + 1.

Значит, итоговая формула ответа:

(pref[r] - pref[l - 1]) / (r - l + 1)

Следовательно, алгоритм вычисляет именно среднюю температуру на заданном отрезке.

5. Сложность

Построение префиксных сумм занимает O(n).

Все остальные действия выполняются за O(1).

Итоговая сложность:

  • по времени: O(n)
  • по памяти: O(n)

6. Код на C++17

#include <iostream>
#include <vector>
#include <iomanip>

using namespace std;

int main() {
    int n;
    cin >> n;

    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;
    }

    int l, r;
    cin >> l >> r;

    long long sum = pref[r] - pref[l - 1];
    int len = r - l + 1;
    double ans = (double)sum / len;

    cout << fixed << setprecision(6) << ans << "\n";
    return 0;
}

7. Код на Python 3

n = int(input())
a = list(map(int, input().split()))
l, r = map(int, input().split())

pref = [0] * (n + 1)
for i in range(1, n + 1):
    pref[i] = pref[i - 1] + a[i - 1]

segment_sum = pref[r] - pref[l - 1]
length = r - l + 1
answer = segment_sum / length

print(f"{answer:.6f}")

Комментарии

Еще нет ни одного комментария.