Lam NguyenLibrary

Library · Utilities

Coordinate Compression

#pragma once
#include <bits/stdc++.h>
using namespace std;

template<class T> struct CoordinateCompressor {
    vector<T> A; 
    
    CoordinateCompressor(vector<T>& arr) {
        A = arr;
        sort(A.begin(), A.end());
        A.erase(unique(A.begin(), A.end()), A.end());
        
        for (auto& x : arr) {
            x = lower_bound(A.begin(), A.end(), x) - A.begin();
        }
    }
    
    T value_at(int rank) const { 
        return A[rank]; 
    }
    
    int rank_of(T x) const { 
        return lower_bound(A.begin(), A.end(), x) - A.begin(); 
    }
    
    int size() const { 
        return A.size(); 
    }
};
from bisect import bisect_left


class CoordinateCompressor:
    # like CoordinateCompression.h: arr is rewritten in place to its ranks
    def __init__(self, arr: list):
        self.A = sorted(set(arr))                       # sort + unique
        self.rank = {x: i for i, x in enumerate(self.A)} # O(1) instead of lower_bound
        arr[:] = [self.rank[x] for x in arr]

    def value_at(self, rank: int):
        return self.A[rank]

    # rank of x; for an x that was never stored, the rank it would take
    def rank_of(self, x) -> int:
        return self.rank[x] if x in self.rank else bisect_left(self.A, x)

    def size(self) -> int:
        return len(self.A)