Редакция для Запросы частоты значения
Submitting an official solution before solving the problem yourself is a bannable offence.
1. Идея
Нужно много раз отвечать на один и тот же тип вопроса: сколько раз число v встречается в массиве.
Если для каждого запроса заново проходить по всему массиву и считать совпадения, получится слишком медленно: q запросов по n элементов, то есть до n * q, а это слишком много.
Поэтому выгодно один раз заранее посчитать, сколько раз встречается каждое значение, а потом для каждого запроса просто брать уже готовый ответ.
Для этого идеально подходит словарь:
- ключ — значение
a_i, - значение — сколько раз оно встретилось.
2. Наблюдения
Запросы независимы друг от друга. Ответ на запрос с кодом
vзависит только от того, сколько разvвстретился в исходной последовательности.Значения могут быть большими и отрицательными. Значит, обычный массив частот использовать неудобно. Нужна структура, которая умеет хранить частоты по произвольным целым ключам. Для этого подходит:
unordered_mapв C++,dictв Python.
После построения таблицы частот каждый запрос обрабатывается очень быстро:
- если значение есть в словаре, выводим его частоту;
- если нет, выводим
0.
3. Алгоритм
- Считать
n. - Считать
nчисел. - Создать словарь частот
freq. - Для каждого числа
xиз последовательности увеличитьfreq[x]на1. - Считать
q. - Для каждого из
qзапросов:- считать
v, - если
vесть в словаре, вывестиfreq[v], - иначе вывести
0.
- считать
4. Почему это работает
После обработки всех n чисел в словаре freq для каждого значения x хранится ровно количество его появлений в последовательности.
Это верно, потому что:
- в начале частота каждого числа равна
0; - каждый раз, когда встречается число
x, мы увеличиваемfreq[x]на1; - значит, после просмотра всей последовательности
freq[x]равно числу элементов, равныхx.
Теперь рассмотрим запрос со значением v:
- если
vбыл в последовательности, вfreq[v]уже записано точное число его вхождений; - если
vне встречался, такого ключа нет в словаре, и ответ должен быть0.
Следовательно, алгоритм выводит правильный ответ для каждого запроса.
5. Сложность
Построение словаря частот:
O(n)в среднем.
Обработка всех запросов:
O(q)в среднем.
Итоговая сложность:
O(n + q)в среднем.
Память:
O(k), гдеk— количество различных значений в последовательности.- В худшем случае
O(n).
6. Код на C++17
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int main() {
int n;
cin >> n;
unordered_map<long long, int> freq;
for (int i = 0; i < n; i++) {
long long x;
cin >> x;
freq[x]++;
}
int q;
cin >> q;
for (int i = 0; i < q; i++) {
long long v;
cin >> v;
if (freq.find(v) != freq.end()) {
cout << freq[v] << '\n';
} else {
cout << 0 << '\n';
}
}
return 0;
}
7. Код на Python 3
n = int(input())
a = list(map(int, input().split()))
freq = {}
for x in a:
if x in freq:
freq[x] += 1
else:
freq[x] = 1
q = int(input())
for _ in range(q):
v = int(input())
print(freq.get(v, 0))
Комментарии