наибольший отрезок
[Условие задачи](в сике взял что-то (TODO))
Условие
Вам дан массив длины до из элементов из диапазона . Найдите максимального длину отрезка массива все элементы которого не меньше .
Решение
Решение
Решение в лоб
Можно написать два цикла для перебора границы отрезка, а затем проверить третьим циклом все элементы в отрезке, но это будет .
int ans = 0;
for (int l = 0; l < n; l++) {
for (int r = l; r < n; r++) {
bool ok = true;
for (int i = l; i <= r; i++) {
if (a[i] < 0) {
ok = false;
break;
}
}
if (ok) {
ans = max(ans, (r - l) + 1);
}
}
}
Можно чуть проще и быстрее, проверку отрезка делать параллельно.
Для этого достаточно понять, что в коде выше во втором цикле когда мы увеличиваем правую границу, то можно сразу проверить отрезок за .
Напишем такой код :
int ans = 0;
for (int l = 0; l < n; l++) {
bool ok = true;
for (int r = l; r < n; r++) {
// ...
}
}
cout << ans;
Подумайте немного, что можно сказать про отрезок , если мы уже знаем ответ для . Аналогично предыдущей задачи про сумму факториалов.
Достаточно посмотреть на a[r]
и если он не подходит, никакие отрезки с нашей левой границей и правой границей правей нашей не будет подходить.
int ans = 0;
for (int l = 0; l < n; l++) {
bool ok = true;
for (int r = l; r < n; r++) {
if (a[r] < 0) {
ok = false;
}
if (ok) {
ans = max(ans, (r - l) + 1);
}
}
}
cout << ans;
Асимптотика решения .
Быстрое решение
Продолжим идею решения выше. Когда a[r] < 0
, можно сделать break
, так-же можно заметить, что если a[r] < 0
, то все отрезки с левой границей меньше r
можно не рассматривать, так как они тоже закончатся в r
.
Такой подход называется два указателя. Первый указатель указывает на начало текущего отрезка, а второй на конец. Вы всего-лишь поддерживаете их в валидном состояние увеличивая в цикле.
int ans = 0;
for (int l = 0; l < n; l++) {
bool ok = true;
for (int r = l; r < n; r++) {
if (a[r] < 0) {
ok = false;
l = r;
break;
}
if (ok) {
ans = max(ans, (r - l) + 1);
}
}
}
cout << ans;
Асимптотика решения .