Количество уникальных элементов на отрезке в онлайне

Revision ru14, by re-wa-tl-ok, 2025-04-04 20:42:29
Задача 1:
Задача 2:

Офлайн обе задачи можно решить с помощью алгоритма Мо и 3DMo (существуют и другие способы, такие как scanline и т. д.), но есть задачи, в которых необходимо отвечать на запросы в онлайн-режиме. Решение с персистентным деревом отрезков, которое я слышал от Andrew-13, неплохое, но оно не поддерживает запросы на обновление. Итак, давайте разберёмся, как решить обе задачи.

Задача 1: $$$O(log(n)^2)$$$ на запрос с использованием 2D Неявного Дерева Отрезков

Что такое "уникальный" элемент на подотрезке? — элемент в подотрезке $$$a[ l, r ]$$$ считается уникальным, если он встречается ровно один раз в этом диапазоне, то есть его предыдущее вхождение (если оно есть) находится перед $$$l$$$, а следующее (если оно есть) — после $$$r$$$.

Введём определение: ссылка элемента $$$a_i$$$ — это указатель на ближайший равный ему элемент слева или справа. Если таких элементов нет, левая ссылка указывает на $$$-1$$$, а правая — на $$$n$$$.

Теперь нам нужно найти количество элементов на отрезке $$$[ l, r ]$$$, таких что их левая ссылка указывает на позицию < $$$l$$$, а правая — на позицию > $$$r$$$. Для этого построим массивы $$$future$$$ и $$$last$$$, содержащие ссылки на ближайшие равные элементы:

$$$future_i$$$ содержит индекс ближайшего элемента, равного $$$a_i$$$ справа (или $$$n$$$, если такого элемента нет).

$$$last_i$$$ содержит индекс ближайшего элемента, равного $$$a_i$$$ слева (или $$$-1$$$, если такого элемента нет).

Рассмотрим текущий запрос: $$$[ l, r ]$$$. Посчитаем количество элементов, у которых $$$future_i$$$ > $$$r$$$ и $$$last_i$$$ < $$$l$$$. Теперь все координаты положительны, так как $$$l$$$, $$$last_i$$$ < $$$n$$$ < $$$10^5$$$.

Таким образом, нам нужно посчитать количество точек ($$$x_i$$$, $$$y_i$$$) = ($$$1000000$$$ — $$$last_i$$$, $$$future_i$$$), которые находятся в верхней правой части плоскости относительно ($$$minX$$$, $$$minY$$$) = ($$$1000000$$$ — $$$l$$$, $$$r$$$). 2D Неявное Дерево Отрезков позволяет сделать это за $$$O(log(n)^2)$$$.

Это было бы решением, если бы не существовали точки:

  1. которые находятся перед левой границей, а их правая ссылка пересекает правую границу.

  2. которые находятся после правой границы, а их левая ссылка пересекает левую границу.

Поэтому нам нужно вычислить количество ненужных точек и вычесть их из общего ответа. Это можно реализовать с помощью простого Дерева Отрезков с Декартовыми Деревьями в узлах, так как нам нужно уметь отвечать на 2 запроса:

  1. посчитать количество элементов на отрезке [ $$$0$$$, $$$l$$$ — $$$1$$$ ], у которых правая ссылка > $$$r$$$.

  2. посчитать количество элементов на отрезке [ $$$r$$$ + $$$1$$$, $$$n$$$ — $$$1$$$ ], у которых левая ссылка < $$$l$$$.

Итог: Предподсчёт ~ $$$O(n * log(n)^2)$$$ Ответ на запрос ~ $$$O(log(n)^2)$$$.

Код
Задача 2: $$$O(log(n)^2)$$$ на запрос с использованием 2D Неявного Дерева Отрезков

Что насчёт запросов на обновление? Заметим, что мы также можем легко отвечать на них за $$$O(log(n)^2)$$$. Обозначим:

$$$L$$$ — максимальная позиция в $$$a$$$, меньшая $$$i$$$, такая что $$$a_L$$$ = $$$X$$$; $$$F$$$ — минимальная позиция в $$$a$$$, большая $$$i$$$, такая что $$$a_F$$$ = $$$X$$$, где $$$X$$$ — это элемент в запросе на обновление. Если таких элементов нет, просто установим: $$$L$$$ = $$$-1$$$, $$$F$$$ = $$$n$$$.

При обновлении элемента $$$a_i$$$ изменяются только ссылки:

  1. $$$a[i]$$$

  2. $$$a[last_i]$$$

  3. $$$a[future_i]$$$

  4. $$$a[L]$$$

  5. $$$a[F]$$$

Остаётся не забыть обновить Дерево Отрезков с Декартовыми Деревьями и точки на 2D плоскости Дерева Отрезков.

Итог: Предподсчёт ~ $$$O(n * log(n)^2)$$$ Ответ на запрос ~ $$$O(log(n)^2)$$$.

Код

Моё решение можно найти здесь.

Tags unique elements counting, уникальные элементы

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
ru14 Russian re-wa-tl-ok 2025-04-04 20:42:29 9 Мелкая правка: '\n\n<spoiler' -> '\n<spoiler'
en7 English re-wa-tl-ok 2025-04-04 15:19:10 299
ru13 Russian re-wa-tl-ok 2025-04-04 15:17:34 300
ru12 Russian re-wa-tl-ok 2025-03-26 23:16:20 7 Мелкая правка: '\n<spoiler s' -> '<spoiler s'
ru11 Russian M1chael_Petrov 2025-03-26 22:42:54 92 Мелкая правка: '\n\n<spoiler' -> '\n<spoiler'
ru10 Russian M1chael_Petrov 2025-03-26 22:39:41 34
ru9 Russian M1chael_Petrov 2025-03-26 22:31:52 8237
en6 English M1chael_Petrov 2025-03-26 22:10:35 0 Tiny change: '\n\n<spoiler' -> '\n<spoiler'
ru8 Russian re-wa-tl-ok 2025-03-26 22:09:38 0 Мелкая правка: '\n\n<spoiler' -> '\n<spoiler'
en5 English re-wa-tl-ok 2025-03-26 22:06:41 0 Tiny change: '\n\n<spoiler' -> '\n<spoiler'
en4 English re-wa-tl-ok 2025-03-26 22:01:12 0 Tiny change: '\n\n<spoiler' -> '\n<spoiler'
en3 English re-wa-tl-ok 2025-03-26 21:55:20 1 Tiny change: '\n\n<spoiler' -> '\n<spoiler'
en2 English re-wa-tl-ok 2025-03-26 21:49:50 1 Tiny change: '\n\n<spoiler' -> '\n<spoiler' (published)
en1 English re-wa-tl-ok 2025-03-26 21:41:17 10622 Initial revision for English translation (saved to drafts)
ru7 Russian re-wa-tl-ok 2025-03-26 21:26:11 0 Мелкая правка: '\n\n<spoiler' -> '\n<spoiler' (опубликовано)
ru6 Russian re-wa-tl-ok 2025-03-26 21:25:25 2
ru5 Russian re-wa-tl-ok 2025-03-26 21:23:32 13 Мелкая правка: '\n<spoiler s' -> '<spoiler s'
ru4 Russian re-wa-tl-ok 2025-03-26 21:17:58 81 Мелкая правка: 'imgur.com/a/7ILXcP6)\n\nSo, w' -> 'imgur.com/bNIHfu7)\n\nSo, w'
ru3 Russian re-wa-tl-ok 2025-03-26 20:36:46 0 Мелкая правка: '\n\n<spoiler s' -> '<spoiler s'
ru2 Russian re-wa-tl-ok 2025-03-26 20:04:22 96
ru1 Russian re-wa-tl-ok 2025-03-26 19:54:04 10466 Первая редакция (сохранено в черновиках)