Блог пользователя kokcio

Автор kokcio, история, 17 часов назад, По-английски

You are given an array which have at most 200000 elements. After that there are q queries. q<=200000. Each query contains three numbers s,e,k. How to for each query answer how many numbers in range [s,e] appear exactly k times? Is there any possibility to solve this without Mo's algorithm?

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
16 часов назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

how do you solve it with mo's?

  • »
    »
    16 часов назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Let's define $$$f(x)$$$ as the frequency of $$$x$$$ in $$$[l, r]$$$, and $$$g(x)$$$ as the number of times frequency $$$x$$$ appeared in $$$[l, r]$$$. Mo's works by "moving" the range for a total of at most $$$\sqrt{n}$$$ times, and each move only takes $$$\mathcal{O}(1)$$$, so we can do this in a total of $$$\mathcal{O}(n\sqrt{n})$$$

»
16 часов назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Merge sort tree in O((N + Q) log^2(N))? Store a map for each range in the segment tree.

Constant factor might be too slow for AC though, especially since N,Q <= 200000. Mo's is probably best.

»
16 часов назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Let's define nums of type map<int, vector<int>>, so that nums[k] returns the list of numbers that appear exactly k times.

Then sort the initial array.

During each query find the it1 = lower_bound(a.begin(), a.end(), s) and it2 = upper_bound(a.begin(), a.end(), e) - 1, which return the leftmost item, not less than s and the rightmost number, not greater than e respectively. Then let it3 = nums.lower_bound(*it1) and chech whether *it3 <= *it2. If condition is satisfied, answer is yes, otherwise it's no.

The total time complexity is O(n log(n))

»
15 часов назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

Upd: oops, didn't see that $$$k$$$ changes on each query. Anyways, here is a solution if $$$k$$$ is fixed throughout.

There is an offline segment tree solution. We will scan the array from left to right and maintain a segment tree. When we are standing at position $$$R$$$, we want the segment tree to store the following data:

For all $$$L$$$ from $$$1$$$ to $$$R$$$: $$$tree[L] =$$$ how many numbers in range $$$[L, R]$$$ appear exactly $$$k$$$ times. Notice that every number $$$X$$$ increments only a particular range of $$$tree$$$: the range between the $$$k$$$-th and $$$(k+1)$$$-th occurence of $$$X$$$ from the back collected so far (up to $$$R$$$).

When we step from $$$R$$$ to $$$R+1$$$, the segment tree does not change too much: the only contribution that changes is the one of $$$A[R+1]$$$. We just need to decrement the previous range, and increment the new range.

Answering a query $$$[s,e]$$$ is simple: when $$$R=e$$$, we extract $$$tree[s]$$$.

So, for this problem you just need a segment tree which allows segment increment + extract single element. You can do it with lazy prop, but actually just a Fenwick tree is enough. TC: $$$O(n \log n)$$$.