Программное решение задач ЕГЭ по информатике

Задача 7015. Источник: Поляков. Задание КИМ 26

Страница задачи 7015

(Л. Шастин) Проспект длиной K метров освещён N фонарями, стоящими вдоль него. Администрация города выяснила, что количество включённых фонарей избыточно для освещения всего проспекта – какие-то из них можно выключить, чтобы сэкономить электроэнергию, при этом проспект все равно останется освещён полностью. Входной файл содержит данные о метках начала и конца отрезков, освещаемых фонарями. Определите, какое максимальное количество фонарей можно выключить так, чтобы проспект остался освещён полностью, а также общее количество фонарей, которые, если их включить, освещают K-й метр проспекта.

Примечание: начало проспекта определено 1-м метром, конец – K-м метром.

Входные данные представлены в файле 26-139.txt следующим образом. В первой строке входного файла находятся два натуральных числа: N (N ≤ 10 000) – количество фонарей, стоящих вдоль проспекта, и K (K ≤ 10 000) – длина проспекта. Следующие N строк содержат пары чисел, обозначающих метку начала и метку конца отрезка проспекта, освещаемого фонарем. Каждое из чисел натуральное, не превосходящее 10 000.

Запишите в ответе два числа: максимальное количество фонарей, которые можно выключить, и количество фонарей, которые, если их включить, освещают K-й метр проспекта.

Пример входного файла:
5 50
1 30
28 50
20 40
1 10
15 50

При таких исходных данных можно выключить 3 фонаря: второй, третий и четвёртый. K-й метр освещается двумя фонарями (если они включены): фонарь {28, 50} и фонарь {15, 50}. Ответ: 3 2.

Решение

Считываем и сортируем исходные данные по началу усвещенного участка. В переменной count будем подсчитывать количество выключенных фонарей, kk - количество фонарей, освещающих k-ый метр, last - первый метр, который нуждается в освещении (инициализируется значением начала участка самого первого фонаря в отсортированных данных)<, max (mx) - максимальный конечный участок среди всех фонарей, которые пересекаются или соприкасаются с последним фонарем, который остался включенным (значение меньше или равно last). Последовательно обрабатываем фонари. Если начальный участок очередного фонаря больше last, "включаем" фонарь, который дал текущее значение max (уменьшаем счетчик count на единицу, а last присваиваем значение max увеличенное на единицу, т.к. этот фонарь осветил участок до данного значения). Обрабатываемый фонарь "выключаем" (увеличиваем count). Если он освещает участок дальше max, меняем значение этой переменной. Если фонарь освещает k-ый метр, увеличиваем счетчик kk. В цикле не будет "включатся" самый последний фонарь с наибольшим max. Поэтому, в качестве результата выводим count уменьшенный на единицу.

Python

f = open('26-139.txt')
n, k = map(int,f.readline().split())
a = [[int(y) for y in x.split()] for x in f]
a.sort()
count = 0
kk = 0
last = a[0][0]
mx = 0
for i in a:
    if i[0] > last:
        count -= 1
        last = mx + 1
    count += 1
    mx = max(mx, i[1])
    if i[0] <= k <= i[1]:
        kk += 1
print(count - 1, kk)

PascalABC

var
    n, k, count, kk, max, last, min, i, j, t: Integer;
    a: array [1..10000, 1..2] of Integer;
    f: TEXT;
begin
    Assign(f, '26-139.txt');
    Reset(f);
    Readln(f, n, k);
    for i := 1 to n do
        Readln(f, a[i, 1], a[i, 2]);
    for i := 1 to n - 1 do
    begin
        min := i;
        for j := i + 1 to n do
            if a[j, 1] < a[min, 1] then
                min := j;
        if min <> i then
        begin
            t := a[i, 1];
            a[i, 1] := a[min, 1];
            a[min, 1] := t;
            t := a[i, 2];
            a[i, 2] := a[min, 2];
            a[min, 2] := t;
        end;
    end;
    count := 0;
    kk := 0;
    last := a[1, 1];
    max := 0;
    for i := 1 to n do
    begin
        if a[i, 1] > last then
        begin
            count := count - 1;
            last := max + 1;
        end;
        count := count + 1;
        if a[i, 2] > max then
            max := a[i, 2];
        if (a[i, 1] <= k) and (a[i, 2] >= k) then
          kk := kk + 1;
    end;
    Writeln(count - 1, ' ', kk);
end.

C++

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    ifstream f;
    f.open("26-139.txt");
    int n, k;
    f >> n >> k;
    int a[10000][2];
    for (int i = 0; i < n; i++)
        f >> a[i][0] >> a[i][1];
    for (int i = 0; i < n - 1; i++)
    {
        int min = i;
        for (int j = i + 1; j < n; j++)
            if (a[j][0] < a[min][0])
                min = j;
        if (min != i)
        {
            int t = a[i][0];
            a[i][0] = a[min][0];
            a[min][0] = t;
            t = a[i][1];
            a[i][1] = a[min][1];
            a[min][1] = t;
        }
    }
    int count = 0, kk = 0, last = a[0][0], max = 0;
    for (int i = 0; i < n; i++)
    {
        if (a[i][0] > last)
        {
            count--;
            last = max + 1;
        }
        count++;
        if (a[i][1] > max)
            max = a[i][1];
        if (a[i][0] <= k && a[i][1] >= k)
            kk++;
    }
    cout << count - 1 << " " << kk << endl;
}

Ответ

9887 3

Отправить замечание по решению

Код по которому имеется замечание:

Ваш вариант кода:

Комментарий: