C++ アルゴリズムとデータ構造のライブラリ
#include "library/sequence/compressor.hpp"get_id: $O(logN)$get_val: $O(1)$vector<long long> A = {10, 40, 90, 90, 150, 420};
// 1. 構築
Compressor<long long> zip(A);
// 2. 種類数の取得
int sz = zip.size(); // 5
// 3. 値から ID への変換 (二分探索)
int id1 = zip.get_id(90); // 2 (90 以上の最小 ID)
int id2 = zip.get_upper_id(90); // 3 (90 より大きい最小 ID)
// 4. ID から元の値への復元
long long val = zip.get_val(2); // 90
// 5. 元の配列をすべて圧縮変換する場合
vector<int> z = zip.get_all();
#pragma once
template <typename T> struct Compressor {
vector<T> origin, dict;
Compressor(const vector<T> &v) : origin(v), dict(v) {
sort(dict.begin(), dict.end());
dict.erase(unique(dict.begin(), dict.end()), dict.end());
}
int size() const { return dict.size(); }
// 値 -> ID (圧縮)
int get_id(T x) const {
return lower_bound(dict.begin(), dict.end(), x) - dict.begin();
}
// 値 -> ID (upper_bound版)
int get_upper_id(T x) const {
return upper_bound(dict.begin(), dict.end(), x) - dict.begin();
}
// ID -> 値 (復元)
T get_val(int id) const { return dict[id]; }
// すべて圧縮
vector<int> get_all() {
vector<int> res;
for (auto &&x : origin) res.emplace_back(get_id(x));
return res;
}
};#line 2 "library/sequence/compressor.hpp"
template <typename T> struct Compressor {
vector<T> origin, dict;
Compressor(const vector<T> &v) : origin(v), dict(v) {
sort(dict.begin(), dict.end());
dict.erase(unique(dict.begin(), dict.end()), dict.end());
}
int size() const { return dict.size(); }
// 値 -> ID (圧縮)
int get_id(T x) const {
return lower_bound(dict.begin(), dict.end(), x) - dict.begin();
}
// 値 -> ID (upper_bound版)
int get_upper_id(T x) const {
return upper_bound(dict.begin(), dict.end(), x) - dict.begin();
}
// ID -> 値 (復元)
T get_val(int id) const { return dict[id]; }
// すべて圧縮
vector<int> get_all() {
vector<int> res;
for (auto &&x : origin) res.emplace_back(get_id(x));
return res;
}
};