Skip to main content

atcoder/lib/algorithm/
compress.rs

1//! 座標圧縮です。
2
3/// スライスを大小関係を保った連番へ変換する拡張トレイトです。
4///
5/// `Ord` を実装する型に利用できます。`[T]` に実装されているため、ベクタや配列からも
6/// スライスとして呼び出せます。
7pub trait Compress<T> {
8    /// 元の値を、重複を除いた昇順列内の順位へ置き換えます。
9    ///
10    /// # Returns
11    ///
12    /// `compressed[i]` は元の `self[i]` に対応する 0-indexed の順位です。`values[j]` は順位
13    /// `j` の元の値で、昇順かつ重複なしです。要素数を `N` とすると `O(N log N)` です。
14    /// 空スライスの場合は、どちらも空のベクタを返します。
15    ///
16    /// # Examples
17    ///
18    /// ```
19    /// use atcoder::algorithm::compress::Compress;
20    ///
21    /// let (compressed, values) = [40, 10, 40, 20].compressed();
22    /// assert_eq!(compressed, [2, 0, 2, 1]);
23    /// assert_eq!(values, [10, 20, 40]);
24    /// ```
25    fn compressed(&self) -> (Vec<usize>, Vec<T>);
26}
27
28impl<T: Ord + Clone> Compress<T> for [T] {
29    fn compressed(&self) -> (Vec<usize>, Vec<T>) {
30        let mut values = self.to_vec();
31        values.sort_unstable();
32        values.dedup();
33        let compressed = self
34            .iter()
35            .map(|value| values.binary_search(value).unwrap())
36            .collect();
37        (compressed, values)
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::Compress;
44
45    #[test]
46    fn compresses_duplicates() {
47        assert_eq!([3, 1, 3].compressed(), (vec![1, 0, 1], vec![1, 3]));
48    }
49}