|
| 1 | +# Задачи про отрезки |
| 2 | + |
| 3 | +Существует такой вид задач, когда нам требуется что-то посчитать на все возможных отрезках. |
| 4 | + |
| 5 | +Задачи выглядят примерно так : |
| 6 | +* Дан массив, найдите количество отрезков, таких что ... |
| 7 | +* Дан массив, для каждой левой границы отрезка найти количество правых границ ИЛИ максимально правую |
| 8 | +* Дан массив, найти минимальный или максимальный отрезок по длине |
| 9 | + |
| 10 | +> Возможен не только массив. Например, реальная задача, на которой я участвовал. |
| 11 | +Даны отрезки и диапазон \\([m_1, m_2]\\). Надо найти количество отрезков \\([a, b]\\), таких что отрезки все отрезки с номерами от \\(a\\) до \\(b\\) при объединение дадут отрезок по длине в диапазоне \\([m_1, m_2]\\). Её я разобрал [здесь](../tasks/cnt-segments-segments.md). |
| 12 | + |
| 13 | +## Решение в лоб |
| 14 | + |
| 15 | +Перебрать все отрезки двумя вложенными циклами, а затем проверить фиксированный отрезок. Ассимптотика данного подхода будет \\(O(n^2 \times c)\\), где \\(O(с)\\), это ассимптотика проверки отрезка, скорее всего она будет линейная, например, перебор всех элементов в отрезке и подсчёт некоторой величины. |
| 16 | + |
| 17 | +Иногда, когда надо проверить фиксированный отрезок, величину можно считать быстрее, например, взять сумму с помощью префиксных сумм или с помощью структур данных. |
| 18 | + |
| 19 | +# Анализ задачи |
| 20 | + |
| 21 | +Скорее всего отрезки имеют некоторые свойства : |
| 22 | + |
| 23 | +1. При фиксированной левой границе, увеличение правой границы на один имеет свойство по которому можно посчитать результат в зависимости от предыдущего результата. |
| 24 | + |
| 25 | +Например, сумма отрезка \\([l, r+1]\\) равна сумме отрезка \\([l, r]\\) плюс элемент \\(a_{r + 1}\\). |
| 26 | + |
| 27 | +2. При фиксированной левой границе, увеличение правой границы, функция "подходит ли отрезок" монотонна. Скорее всего при увеличение правой границы, отрезок сначала подходит, а потом перестаёт подходить (наоборот всё тоже работает, я просто таких задач не встречал). |
| 28 | + |
| 29 | +Например, в задаче надо найти количество отрезков, таких что `gcd` элементов на отрезке больше \\(k\\). (\\(gcd\\) наибольший общий делитель). Важное нам свойство \\(gcd(a, b) \le min(a, b)\\), значит при увеличение правой границы отрезок сначала подходит, а потом перестаёт подходить. |
| 30 | + |
| 31 | +3. Монотонность при передвижение левой границы. Если отрезок \\([l, r]\\) подходит, то |
| 32 | +отрезок \\([l + 1, r]\\) тоже подходит. Причём это свойство без учёта монотонности по правой границе. |
| 33 | + |
| 34 | +Это достаточно искусственный пример, но всё же : отрезок подходит, если сумма на отрезке делённая на самый **правый** элемент отрезка больше \\(k\\). В таком случае при увеличение левой границе сумма уменьшается, а следовательно отрезок продолжает подходить если подходил, и даже может подходить если не подходил. Но при увеличение правой границы из-за деления могут последовать любые результаты. |
| 35 | + |
| 36 | +Почти всегда если выполняется `2`-ое свойство то и `3`-е тоже выполняется. По отдельности выполнение `3`-е свойства без `2`-го возможно, но если перевернуть массив, то получится монотонность по правой и `2`-е свойство. |
| 37 | + |
| 38 | +# Алгоритмы |
| 39 | + |
| 40 | +Если свойство `1` выполняется, то что-то можно сделать. TODO я особо не знаю |
| 41 | + |
| 42 | +Если свойство `2` выполняется, то можно сделать бинпоиск по правой границе при фиксированной левой. |
| 43 | + |
| 44 | +Если свойство `2` и `3` выполняется, то можно применить два указателя, но бинпоиск тоже работает (но всё же там уже лишний \\(\log\\)). |
| 45 | + |
| 46 | +Иногда можно применить технику "разделяй и властвуй" или динамическое программирование. |
| 47 | + |
| 48 | +Почти всегда бинпоиск со структурой данных с условных \\(O(\log^2)\\) на запрос можно заменить на спуск по дереву отрезок, что будет \\(O(\log\\). |
| 49 | + |
| 50 | +# Практические задачи |
| 51 | + |
| 52 | +* [Опасные группы отрезков](../tasks/cnt-segments-segments.md). Разобрана. |
| 53 | +* [Перемножь последовательность!](). Моя задача. TODO |
| 54 | +* CGCDSSQ исходники в слонах |
0 commit comments