Бесплатный урок с нашим репетитором!

Узнать подробнее

Новая Школа - онлайн-школа подготовки к ЕГЭ
При поддержке
Посмотреть все вопросы нейросети
Бесплатный пробный урок с репетитором

Узнай больше про репетиторов Новой Школы и запишись на бесплатный пробный урок. Мы проверим твой уровень знаний и составим план обучения по любому предмету и классу

Вопрос от Анонимного юзера 11 сентября 2025 10:16

Реши задачу на python и c++

Ответ нейросети

11 сентября 2025 10:16

Ниже решение задачи на двух языках: Python и C++. Задача: дан массив a длины n и число k. Нужно минимальное количество дней вставить внутрь календаря так, чтобы не осталось ни одного непустого подотрезка, сумма элементов которого равна k. Вставляемые дни можем заполнить любыми целыми числами.

Идея

  • Любой подотрезок [l..r], сумма равна k, делает проблему “нужны вставки” активной: чтобы этот подотрезок перестал существовать как непрерывный, нужно вставить хотя бы один элемент внутри него. Таким образом задача эквивалентна минимальному набору точек разрыва между соседними элементами (между i и i+1, т.е. между позициями 1..n-1) так, чтобы каждый подотрезок, сумма которого равна k, содержал хотя бы одну такую точку разрыва.
  • Это классическая задача о минимальном количестве точек, которые пересекают все интервалы ( stabbing/хитинг сет для интервалов). Для интервалов оптимальным жестким алгоритмом является жадный: ставим точку в правый конец первого по завершению интервала, удаляем все интервалы, пересекаемые этой точкой, и повторяем.
  • Проблема в том, что может быть много таких подотрезков (особенно если есть нули). Мы можем обойтись без явного перечисления всех подотрезков: пройдём по r от 1 до n и проверим, существует ли подотрезок, заканчивающийся в r, сумма которого равна k и который не пересекается с уже поставленными разрыва(ами). Пусть last_cut — индекс последнего поставленного разрыва (между last_cut и last_cut+1). Подотрезок [l..r] не пересекает этот разрыв тогда, когда l > last_cut.
  • Сумма подотрезка [l..r] равна k тогда, если prefix[r] - prefix[l-1] = k, где prefix[i] — префикс сумма. Значит, существует l такое, что prefix[l-1] = prefix[r] - k. Если мы хотим, чтобы подотрезок не пересекался с предыдущими разрывами, то l-1 должен быть не меньше last_cut, то есть t = l-1 ∈ [last_cut, r-1].
  • Для быстрых проверок создаём для каждого значения префиксной суммы список всех индексов i, для которых prefix[i] = значение. Тогда для каждого r ищем есть ли t в списке prefix[r]-k, который лежит в диапазоне [last_cut, r-1]. Это делается бинарным поиском.
  • Если такой t существует, ставим новый разрыв между r-1 и r, т.е. last_cut = r-1, и увеличиваем ответ.

Сложность: O(n log n) — один бинарный поиск на каждом r. Память: O(n).

Python (решение)

import sys
import bisect

def solve():
    data = sys.stdin.read().strip().split()
    if not data:
        return
    it = iter(data)
    n = int(next(it))
    k = int(next(it))
    a = [int(next(it)) for _ in range(n)]

    # Префиксные суммы
    pref = [0] * (n + 1)
    for i in range(1, n + 1):
        pref[i] = pref[i - 1] + a[i - 1]

    # Для каждого значения префикса сохраняем список позиций i (от 0 до n)
    pos = {}
    for i, val in enumerate(pref):
        if val not in pos:
            pos[val] = []
        pos[val].append(i)

    last_cut = -1  # последний поставленный разрыв между last_cut и last_cut+1
    ans = 0

    for r in range(1, n + 1):
        target = pref[r] - k
        if target in pos:
            lst = pos[target]
            # Найти первый t >= last_cut
            idx = bisect.bisect_left(lst, last_cut)
            if idx < len(lst) and lst[idx] <= r - 1:
                # Существует подотрезок [l..r] с суммой k и l-1 = lst[idx] >= last_cut
                ans += 1
                last_cut = r - 1

    print(ans)

if __name__ == "__main__":
    solve()

C++ (решение)

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    long long k;
    if (!(cin >> n >> k)) return 0;

    vector<long long> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i];

    // Префиксные суммы
    vector<long long> pref(n + 1, 0);
    for (int i = 1; i <= n; ++i) pref[i] = pref[i - 1] + a[i - 1];

    // карта префиксных значений -> вектор индексов
    unordered_map<long long, vector<int>> pos;
    pos.reserve(n * 2);
    for (int i = 0; i <= n; ++i) {
        pos[pref[i]].push_back(i);
    }

    long long last_cut = -1; // последний разрыв между last_cut и last_cut+1
    int ans = 0;

    for (int r = 1; r <= n; ++r) {
        long long target = pref[r] - k;
        auto it = pos.find(target);
        if (it != pos.end()) {
            const vector<int>& lst = it->second;
            // Найти первый индекc t >= last_cut
            auto itlb = lower_bound(lst.begin(), lst.end(), (int)last_cut);
            if (itlb != lst.end() && *itlb <= r - 1) {
                // существует подотрезок [l..r] с суммой k, не пересекающий предыдущий разрыв
                ++ans;
                last_cut = r - 1;
            }
        }
    }

    cout << ans << "\n";
    return 0;
}

Коротко о примерах

  • Пример 1: n=5, k=1, массив большие числа. Нет подотрезков суммы 1 => ответ 0.
  • Пример 2: n=5, k=4, массив [-4, 3, 5, 0, 1]. Есть подотрезок, сумма которого равна 4 (например, -4+3+5 и т.д.). Один разрыв внутри этого подотрезка достаточно, чтобы уничтожить все такие подотрезки. Ответ 1.

Задай свой вопрос

Напиши любую задачу или вопрос, а нейросеть её решит

Похожие вопросы 15

Бесплатно Мобильное приложение ГДЗ
Мобильное приложение ГДЗ

Задавай вопросы искуcственному интеллекту текстом или фотографиями в приложении на iPhone или Android

qr-codegoogle-playapp-store

Саша — ассистент в телеграмме

Реши задачу на python и c++
Ниже решение задачи на двух языках: Python и C++. Задача: дан массив a длины n и число k. Нужно минимальное количество дней вставить внутрь календаря так, чтобы не осталось ни одного непустого подотрезка, сумма элементов которого равна k. Вставляемые дни можем заполнить любыми целыми числами. Идея - Любой подотрезок [l..r], сумма равна k, делает проблему “нужны вставки” активной: чтобы этот подотрезок перестал существовать как непрерывный, нужно вставить хотя бы один элемент внутри него. Таким образом задача эквивалентна минимальному набору точек разрыва между соседними элементами (между i и i+1, т.е. между позициями 1..n-1) так, чтобы каждый подотрезок, сумма которого равна k, содержал хотя бы одну такую точку разрыва. - Это классическая задача о минимальном количестве точек, которые пересекают все интервалы ( stabbing/хитинг сет для интервалов). Для интервалов оптимальным жестким алгоритмом является жадный: ставим точку в правый конец первого по завершению интервала, удаляем все интервалы, пересекаемые этой точкой, и повторяем. - Проблема в том, что может быть много таких подотрезков (особенно если есть нули). Мы можем обойтись без явного перечисления всех подотрезков: пройдём по r от 1 до n и проверим, существует ли подотрезок, заканчивающийся в r, сумма которого равна k и который не пересекается с уже поставленными разрыва(ами). Пусть last_cut — индекс последнего поставленного разрыва (между last_cut и last_cut+1). Подотрезок [l..r] не пересекает этот разрыв тогда, когда l > last_cut. - Сумма подотрезка [l..r] равна k тогда, если prefix[r] - prefix[l-1] = k, где prefix[i] — префикс сумма. Значит, существует l такое, что prefix[l-1] = prefix[r] - k. Если мы хотим, чтобы подотрезок не пересекался с предыдущими разрывами, то l-1 должен быть не меньше last_cut, то есть t = l-1 ∈ [last_cut, r-1]. - Для быстрых проверок создаём для каждого значения префиксной суммы список всех индексов i, для которых prefix[i] = значение. Тогда для каждого r ищем есть ли t в списке prefix[r]-k, который лежит в диапазоне [last_cut, r-1]. Это делается бинарным поиском. - Если такой t существует, ставим новый разрыв между r-1 и r, т.е. last_cut = r-1, и увеличиваем ответ. Сложность: O(n log n) — один бинарный поиск на каждом r. Память: O(n). Python (решение) ```python import sys import bisect def solve(): data = sys.stdin.read().strip().split() if not data: return it = iter(data) n = int(next(it)) k = int(next(it)) a = [int(next(it)) for _ in range(n)] # Префиксные суммы pref = [0] * (n + 1) for i in range(1, n + 1): pref[i] = pref[i - 1] + a[i - 1] # Для каждого значения префикса сохраняем список позиций i (от 0 до n) pos = {} for i, val in enumerate(pref): if val not in pos: pos[val] = [] pos[val].append(i) last_cut = -1 # последний поставленный разрыв между last_cut и last_cut+1 ans = 0 for r in range(1, n + 1): target = pref[r] - k if target in pos: lst = pos[target] # Найти первый t >= last_cut idx = bisect.bisect_left(lst, last_cut) if idx < len(lst) and lst[idx] <= r - 1: # Существует подотрезок [l..r] с суммой k и l-1 = lst[idx] >= last_cut ans += 1 last_cut = r - 1 print(ans) if __name__ == "__main__": solve() ``` C++ (решение) ```cpp #include using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; long long k; if (!(cin >> n >> k)) return 0; vector a(n); for (int i = 0; i < n; ++i) cin >> a[i]; // Префиксные суммы vector pref(n + 1, 0); for (int i = 1; i <= n; ++i) pref[i] = pref[i - 1] + a[i - 1]; // карта префиксных значений -> вектор индексов unordered_map> pos; pos.reserve(n * 2); for (int i = 0; i <= n; ++i) { pos[pref[i]].push_back(i); } long long last_cut = -1; // последний разрыв между last_cut и last_cut+1 int ans = 0; for (int r = 1; r <= n; ++r) { long long target = pref[r] - k; auto it = pos.find(target); if (it != pos.end()) { const vector& lst = it->second; // Найти первый индекc t >= last_cut auto itlb = lower_bound(lst.begin(), lst.end(), (int)last_cut); if (itlb != lst.end() && *itlb <= r - 1) { // существует подотрезок [l..r] с суммой k, не пересекающий предыдущий разрыв ++ans; last_cut = r - 1; } } } cout << ans << "\n"; return 0; } ``` Коротко о примерах - Пример 1: n=5, k=1, массив большие числа. Нет подотрезков суммы 1 => ответ 0. - Пример 2: n=5, k=4, массив [-4, 3, 5, 0, 1]. Есть подотрезок, сумма которого равна 4 (например, -4+3+5 и т.д.). Один разрыв внутри этого подотрезка достаточно, чтобы уничтожить все такие подотрезки. Ответ 1.