Official

C - The Kth Time Query Editorial by en_translator


This problem can be efficiently solved with a data structure called associative array.

Prepare an associative array whose keys are “the integers appears in \(A\)” and whose values are “the arrays that stores the indices of occurrences of the value in the increasing order.”
For example, when \(N = 6, A = (1, 1, 2, 3, 1, 2)\), the data structure (named \(m\) here) will look like

\[ \begin{aligned} m\lbrack 1 \rbrack &= \lbrace 1, 2, 5 \rbrace \\ m \lbrack 2 \rbrack &= \lbrace 3, 6 \rbrace \\ m \lbrack 3 \rbrack &= \lbrace 4 \rbrace. \end{aligned} \]

Once we obtained the associative array, the queries can be processed fast.
Specifically, when you receive a query \((x, k)\), do the following operations.

  • Refer to \(m\lbrack x \rbrack\) and its length.
    • If the length of \(m \lbrack x \rbrack\) is at least \(k\), output the \(k\)-th leftmost element of \(m\lbrack x \rbrack\).
    • If the length of \(m \lbrack x \rbrack\) is less than \(k\), output \(-1\).

The complexity is \(\mathrm{O}((N + Q)T)\), where \(T\) is that for looking up the element of the associative array. For example, std::map in C++ requires \(T = \mathrm{O}(\log N)\), so the overall complexity will be \(\mathrm{O}((N + Q)\log N)\).

Here is a sample code in Python.

from collections import defaultdict

N, Q = map(int, input().split())
A = list(map(int, input().split()))

m = defaultdict(list)
for i in range(N):
  m[A[i]].append(i + 1)

for _ in range(Q):
  x, k = map(int, input().split())
  if k <= len(m[x]):
    print(m[x][k - 1])
  else:
    print(-1)

posted:
last update: