4-й этап Республиканской олимпиады по информатике 2021-2022, 2 тура
Есеп В. MEXI
Нархан Аза-ға келесі есепті ұсынды: Сізге мөлшері $n$ болатын бүтін сандардан тұратын $a$ массиві берілген. $a$ массивін $k$ бөлікке $(l_1, r_1), \ldots, (l_k, r_k)$ бөлуін $x$-жақсы бөлініс деп атаймыз егер келесі шарттар орындалса:
- $a$ массивының кез-келген элементі дәл бір бөлікте жатады.
- Кез келген $1 <= i <= k$ үшін, $(a_{l_i}, \ldots, a_{r_i})$ сандарының $MEX$і $x$-тен кіші немесе тең болады.
- $[2,2,1]$ $MEX$i $0$, себебі $0$ массивте кездеспейді.
- $[3,1,0,1]$ $MEX$і $2$, себебі $0$ жәңе $1$ массивте кездеседі, ал $2$ — жоқ.
- $[0,3,1,2]$ $MEX$і $4$, себебі $0$, $1$, $2$ жәңе $3$ массивте кездеседі, ал $4$ — жоқ.
4 0 1 0 2Ответ
-1 3 2 1Вход
1 2Ответ
1
- $x = 0$ болғанда, жақсы бөлініс жоқ, сол себепті $-1$ шығарамыз.
- $x = 1$ болғанда, $3$ бөлікке бөлеміз: [$0$],[$1$],[$0,2$].
- $x = 2$ болғанда, $2$ бөлікке бөлеміз: [$0,1$], [$0,2$].
- $x = 3$ болғанда, бір бөлік массивтың өзі [$0,1,0,2$].
Комментарий/решение:
Алгоритм:
Создаем множество set_nums, в котором будем хранить все уникальные элементы массива a.
Находим минимальный элемент min_a в массиве a.
Если min_a равен 0, то выводим 1, так как разделение на отрезки единственное и состоит из всех элементов массива.
Иначе, если 0 не содержится в set_nums, то выводим 0, так как невозможно построить хорошее разделение.
Иначе, создаем переменную cur, равную минимальному элементу min_a, и удаляем его из множества set_nums.
Запускаем цикл от 1 до n+1:
Если cur содержится в set_nums, то удаляем его из множества и увеличиваем cur на 1.
Иначе, выводим текущее значение цикла и завершаем программу.
Блок-схема:
+-------------------------+
| Создать множество set |
| для уникальных элементов|
| массива a |
+-------------------------+
|
|
|
v
+----------------+
| Найти min_a в a |
+----------------+
|
|
|
v
+-------------------+
| Если min_a = 0, |
| вывести 1 и выйти|
+-------------------+
|
|
|
v
+---------------+
| Если 0 нет в |
| set_nums, |
| вывести 0 и |
| выйти |
+---------------+
|
|
|
v
+-------------------+
| Создать cur = min_a|
| и удалить его из |
| set_nums |
+-------------------+
|
|
|
v
+---------------+
| Для i от 1 до n+1|
+---------------+
|
|
|
v
+--------------------------+
| Если cur в set_nums, |
| удалить его и увеличить |
| cur на 1 |
+--------------------------+
|
|
+-----------+-------+
| | |
| v |
| Если cur не в |
| set_nums, вывести i |
| и завершить программу|
| |
v v
Алгоритм решения:
Создаем массив a[1000001] и инициализируем его нулями.
Считываем массив чисел входного файла и для каждого числа i, устанавливаем a[i] равным единице.
Выполняем проход по a, начиная с 0, и считаем количество пройденных нулей (count) и единиц (ones).
Если count + ones = n, где n - размер массива, то выводим 1, иначе выводим 2.
Пояснения:
a[i] будет равно 1, если число i содержится в массиве nums.
count - количество нулей, которые мы прошли в массиве a.
ones - количество единиц, которые мы прошли в массиве a.
Если мы прошли все элементы массива a и count + ones не равно n, то это означает, что есть число, которое не содержится в массиве. Поэтому для любого числа i от 0 до n мы можем создать разделение, в котором i не встречается, и количество отрезков в этом разделении будет равно i + 1.
Временная сложность алгоритма: O(n).
Блок-схема алгоритма:
+--------+
| Старт |
+--------+
|
v
+-----------------+
| Инициализация |
+-----------------+
|
v
+-----------------+
| Считать массив |
+-----------------+
|
v
+-----------------+
| Обработка |
+-----------------+
|
v
+-----------------+
| Вывод |
+-----------------+
|
v
+--------+
| Финиш |
+--------+
Код на языке C++:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
vector<int> a(1000001, 0);
for (int i = 0; i < n; i++) {
a[nums[i]] = 1;
}
int count = 0, ones = 0;
for (int i = 0; i <= n; i++) {
if (a[i] == 0) {
count++;
} else {
ones++;
}
if (count + ones == n) {
cout << "1\n";
return 0;
}
}
for (int i = 0; i < n; i++) {
if (nums[i] >= n) {
cout << "2\n";
return 0;
}
}
for (int i = 0; i < n; i++) {
if (a[i] == 0) {
cout << i + 1 << "\n";
return 0;
}
}
return 0;
}
Что за позер, сейчас бы ChatGPT использовать ради того, чтоб дать свой коммент? Удали, или если у тебя есть весомая цель чтоб публиковать это, оборачивай в читаемый и спойлер код.
Возможно, что при неправильном наборе формул, они будут
доредактированы модератором. При этом содержание не будет меняться.