Не раз вижу, что для использования какого-нибудь алгоритма, имеющего дело с большими числами, нужно предварительно сжать эти числа, однако поиск самого алгоритма сжатия ничего не дал. Правильно ли я понимаю, что для этого нужно создать массив пар <число, ссылка на число в прежнем массиве>, отсортировать его и по порядку перенумеровать числа с 1?
В массиве B уже сжатый массив A.
И... оно фигово работает, когда в массиве a есть одинаковые числа.
Насколько я понимаю, нужно увеличивать присваиваемое b[a[i].second] число только тогда, когда очередное a[i] имеет значение, отличное от значения a[i-1]. Тогда этот алгоритм будет корректным.
Да и таким способом не очень удобно восстанавливать первоначальные значения.
Короче, есть три способа.
Посортить, как уже выше написали, пары (a[i], i). Потом в новый массив записывать числа по порядку на индексы a[i].second, при этом если a[i].first не меняется, записываемое число тоже не должно меняться.
Добавить все числа в сет. Потом пройтись по сету и сохранить в мапе, что первый элемент сета будет 1, второй элемент сета будет 2, и т.д. Потом заменить числа в исходном массиве как a[i] = mp[a[i]].
(мне кажется, это лучший способ) Посортить копию массива и убрать дубликаты. Потом бинпоиском найти позицию каждого элемента в этом массиве: a[i] = lower_bound(copy.begin(), copy.end(), a[i]) — copy.begin()
А что, если мне потом надо будет быстро преобразовывать сжатое число в несжатое? В новом массиве хранить пары <сжатое число, номер в несжатом и неотсортированном>?
Обычно обратно преобразовывать не нужно (я ни разу не видел, чтоб было нужно), но если все-таки нужно, наиболее очевидный способ — просто сохранить эту инфу в map. Даже можно не в map, а просто в массив, т.к. все ключи — сжатые числа, и они от 1 до n.
Обратно бывает нужно во всяких задачах на отрезки (типа площади объединения прямоугольников). В твоём случае никакой map не нужен же, достаточно посмотреть на copy[i].
Tips&tricks:
и забываем про shr.
3. Не надо использовать map. Это в разы дольше, я так ловил TL-и. map стоит использовать только если координаты не известны заранее.
всегда пишу простой код с sort+lower_bound, но вообще можно обойтись одной сортировкой и одним дополнительным массивом: