Find the number of unique elements on segment online

Правка ru6, от re-wa-tl-ok, 2025-03-26 21:25:25
Problem 1:
Problem 2:

Of course, offline, both tasks can be solved using Mo algorithm and 3DMo (there are many ways like scanline, etc.), but there are some problems where we need to answer queries online. The solution with a persistent segment tree, i heard from Andrew-13, is good, but it does not support update queries. So, let's get started and learn how to solve both problems.

Problem 1: $$$O(log(n)^2)$$$ on query using 2D Implicit Segment Tree

What is a "unique" element in a subarray? — an element in a subarray $$$a[ l, r ]$$$ is considered unique if it appears exactly once in that range => it's previous occurrence (if any) is before $$$l$$$ and it's next occurrence (if any) is after $$$r$$$.

Let's introduce the definition: link of $$$a_i$$$ is a reference that points to an equal element that is located closer to the left/right than others. If there are no such links, the left link leads to $$$-1$$$, and the right link leads to $$$n$$$.

Now we need to find the number of elements on $$$[ l, r ]$$$ such that their left links point to elements at positions < $$$l$$$, and the right links to elements at positions > $$$r$$$. So, let's build $$$future$$$ and $$$last$$$ — arrays containing links to the closest equal elements:

  1. $$$future_i$$$ contains the index of the closest element equal to $$$a_i$$$ on the right (or $$$n$$$ if there are no such elements).
  2. $$$last_i$$$ contains the index of the closest element equal to $$$a_i$$$ on the left (or $$$-1$$$ if there are no such elements).

We will consider current query: $$$[ l, r ]$$$. Let's just count elements with $$$future_i$$$ > $$$r$$$ and $$$last_i$$$ < $$$l$$$ => — $$$last_i$$$ > — $$$l$$$ => $$$1000000$$$ — $$$last_i$$$ > $$$1000000$$$ — $$$l$$$. Now all coordinates are positive, because $$$l$$$, $$$last_i$$$ < $$$n$$$ < $$$10^5$$$.

So, we need to count the number of points ($$$x_i$$$, $$$y_i$$$) = ($$$1000000$$$ — $$$last_i$$$, $$$future_i$$$) which lie in the upper right part of plane relative to ($$$minX$$$, $$$minY$$$) = ($$$1000000$$$ — $$$l$$$, $$$r$$$). 2D Implicit Segment Tree can easily solve this problem in $$$O(log(n)^2)$$$.

This would be a solution if there were no points:

  1. lies before the left border and the right link crosses the right border.
  2. lies after the right border and the left link crosses the left border.

So, we get the number of unnecessary points and subtract it from the total answer. This can be realized with simple Segment Tree with Treaps in nodes, because we actually need to be able to answer to 2 queries:

  1. count the number of elements on [ $$$0$$$, $$$l$$$ — $$$1$$$ ] that have right links > $$$r$$$.
  2. count the number of elements on [ $$$r$$$ + $$$1$$$, $$$n$$$ — $$$1$$$ ] that have left links < $$$l$$$.

Finally: Precalc ~ $$$O(n * log(n)^2)$$$; Answer to query ~ $$$O(log(n)^2)$$$.

Code
Problem 2: $$$O(log(n)^2)$$$ on query using 2D Implicit Segment Tree

What about update queries? Note that we can also easily answer them in $$$O(log(n)^2)$$$. Let's call $$$L$$$ — the maximum position in $$$a$$$ that < $$$i$$$ and $$$a_L$$$ = $$$X$$$; $$$F$$$ — the minimum position in $$$a$$$ that > $$$i$$$ and $$$a_F$$$ = $$$X$$$, where $$$X$$$ is the element in the update query. If there are no such elements, just put: $$$L$$$ = $$$-1$$$; $$$F$$$ = $$$n$$$.

When updating an element $$$a_i$$$, the links only change:

  1. $$$a[i]$$$ links.
  2. $$$a[last_i]$$$ links.
  3. $$$a[future_i]$$$ links.
  4. $$$a[L]$$$ links.
  5. $$$a[F]$$$ links.

It remains to remember to update Segment Tree of Treaps and the points on the 2D Segment Tree plane.

Finally: Precalc ~ $$$O(n * log(n)^2)$$$; Answer to query ~ $$$O(log(n)^2)$$$.

Code

You can find my solution here.

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

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
ru14 Русский re-wa-tl-ok 2025-04-04 20:42:29 9 Мелкая правка: '\n\n<spoiler' -> '\n<spoiler'
en7 Английский re-wa-tl-ok 2025-04-04 15:19:10 299
ru13 Русский re-wa-tl-ok 2025-04-04 15:17:34 300
ru12 Русский re-wa-tl-ok 2025-03-26 23:16:20 7 Мелкая правка: '\n<spoiler s' -> '<spoiler s'
ru11 Русский M1chael_Petrov 2025-03-26 22:42:54 92 Мелкая правка: '\n\n<spoiler' -> '\n<spoiler'
ru10 Русский M1chael_Petrov 2025-03-26 22:39:41 34
ru9 Русский M1chael_Petrov 2025-03-26 22:31:52 8237
en6 Английский M1chael_Petrov 2025-03-26 22:10:35 0 Tiny change: '\n\n<spoiler' -> '\n<spoiler'
ru8 Русский re-wa-tl-ok 2025-03-26 22:09:38 0 Мелкая правка: '\n\n<spoiler' -> '\n<spoiler'
en5 Английский re-wa-tl-ok 2025-03-26 22:06:41 0 Tiny change: '\n\n<spoiler' -> '\n<spoiler'
en4 Английский re-wa-tl-ok 2025-03-26 22:01:12 0 Tiny change: '\n\n<spoiler' -> '\n<spoiler'
en3 Английский re-wa-tl-ok 2025-03-26 21:55:20 1 Tiny change: '\n\n<spoiler' -> '\n<spoiler'
en2 Английский re-wa-tl-ok 2025-03-26 21:49:50 1 Tiny change: '\n\n<spoiler' -> '\n<spoiler' (published)
en1 Английский re-wa-tl-ok 2025-03-26 21:41:17 10622 Initial revision for English translation (saved to drafts)
ru7 Русский re-wa-tl-ok 2025-03-26 21:26:11 0 Мелкая правка: '\n\n<spoiler' -> '\n<spoiler' (опубликовано)
ru6 Русский re-wa-tl-ok 2025-03-26 21:25:25 2
ru5 Русский re-wa-tl-ok 2025-03-26 21:23:32 13 Мелкая правка: '\n<spoiler s' -> '<spoiler s'
ru4 Русский 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 Русский re-wa-tl-ok 2025-03-26 20:36:46 0 Мелкая правка: '\n\n<spoiler s' -> '<spoiler s'
ru2 Русский re-wa-tl-ok 2025-03-26 20:04:22 96
ru1 Русский re-wa-tl-ok 2025-03-26 19:54:04 10466 Первая редакция (сохранено в черновиках)