Find the number of unique elements on segment online

Revision ru6, by 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.

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 Первая редакция (сохранено в черновиках)