Разбор первого тура
Задача А: Кинотеатр
Давайте выделим множество точек, которые находятся на расстоянии K от какого-нибудь экрана. Для каждого экрана это будут два отрезка (прямоугольника 1 × x), параллельные экрану на расстоянии K от него. Множество интересующих нас точек — подмножество объединения этих отрезков.
Теперь поймем, какие точки из объединения нас не интересуют. Для каждого экрана множество точек, расстояние от которых до него строго меньше, чем K — это прямоугольник. Все точки, принадлежащие хотя бы одному такому прямоугольнику, точно не входят в ответ.
Понятно, что на самом деле нас интересует разность объединения множества отрезков и множества прямоугольников.
Таким образом, задача свелась к следующей: посчтать площадь разности объединения множества отрезков A и множества прямоугольников B. Можно отдельно решить задачу для вертикальных и горизонтальных отрезков (здесь важно не учесть точки пересечения дважды, то есть, рассматривая вертикальные отрезки, нужно добавить горионтальные в множество B).
Для вертикальных отрезков решим задачу с помощью сканирующей прямой: будем двигать вертикальную прямую в сторону увеличения x и поддерживать дерево отрезков a, a[y] = 1, если точка (x,y) покрыта каким-нибудь прямоугольником из B и a[y] = 0 в противном случае. Тогда для каждого x выделим множество непересекающихся отрезков с таким x и для каждого добавим к ответу (здесь y1 и y2 — координаты концов отрезка).
Задача B: Робот в лабиринте
Задачу можно было решать стандартным методом обхода по правилу правой руки. То есть, изначально робот находится в некоторой клетке, он поворачивает направо, пробует пойти вперед, если это удается, то можно вернуться в первоначальное состояние, если нет, робот поворачивается влево и снова пробует пойти вперед, если на этот раз пойти вперед можно, то робот возвращается в первоначальное состояние, если нет, то робот снова поворачивает налево (в итоге робот должен попробовать пойти во всех возможных направлениях, начиная с самого правого.
По такому алгоритму робот будет двигаться вдоль стенки. Из-за того, что лабиринт в задаче является деревом, так можно обойти все клетки.
Задача C: Игра с камнями
Для маленьких n можно было решать задачу с помощью функции гранди По такой формуле все значения g можно посчитать за O(n3). Но, на самом деле, можно заметить, что и просто делать переход в состояние игры с ненулевой функцией Гранди (выигрышных переходов достаточно много, поэтому можно перебирать их случайно или в каком-нибудь хорошем порядке).
Второй вариант решения — заметить, что из состояния n можно перейти либо в состояние 1, x, x, либо в состояние 2, x, x и далее делать ходы симметричные ходам второго игрока.
Задача D: Подстрока подстроки
Если бы все строки в запросах были одной длины K, то задачу можно было бы решать следующим образом:
- Сохраним для каждого индекса i хэш подстроки si, …, si+K-1 = h[i]
- Когда приходит запрос [l,r], нужно посчитать количество индексов на отрезке [l, r-K+1], таких, что h[i] = x
- Давайте отсортируем пары (h[i],i).
- Искомое количество индексов — количество пар, лежащих в списке между парами (x,l) и (x,r-K+1) (нестрого)
- Таким образом, на запрос можно ответить с помощью двух бинпоисков
Давайте для длин ≤ C посчитаем массивы h[i] и отсортируем массивы пар (h[i],i), а для запросов длины >C будем решать задачу для каждого запроса за O(|s| + l) с помощью префикс-функции (здесь l — длина строки в запросе). Таким образом, получилось решение за . S — суммарная длина строк-запросов.
Можно подобрать C так, чтобы эта величина была достаточно мала.