본문 바로가기
PS/BOJ

[BOJ 18870] 좌표 압축

by Saerong2 2020. 7. 16.

 

 

문제 링크

https://www.acmicpc.net/problem/18870

 

18870번: 좌표 압축

수직선 위에 N개의 좌표 X1, X2, ..., XN이 있다. 이 좌표에 좌표 압축을 적용하려고 한다. Xi를 좌표 압축한 결과 X'i의 값은 Xi > Xj를 만족하는 서로 다른 좌표의 개수와 같아야 한다. X1, X2, ..., XN에 좌

www.acmicpc.net

 


아이디어

 

'좌표압축' 기법은 PS에서 종종 쓰이는 기법으로,

큰 범위의 값을 갖는 좌표들을 정렬하여 다시 순서를 부여함으로써, 더 작은 범위 내로 압축 시키는 것이다.

 

가령 1차원 x축 위의 [1, 1e9] 의 값을 갖는 어떤 1만 개의 좌표를 생각해보자.

count[t] = x축의 값이 t인 좌표의 개수라고 할 때,

t = [1, 1e9]인 좌표의 개수를 저장하기 위해 필요한 최소의 count 배열의 크기는 1e9이다.

하지만, 1e9 + 1개의 칸중에서 실제로 사용하는 칸은 오직 1만 개이며, 나머지 빈칸은 사용하지 않는다.

이 사이사이의 비어있는 칸을 없애는 것이 좌표압축의 아이디어이다.

 

실제 좌표의 개수는 1만개이기 때문에, 좌표값의 대소비교를 통해 순서를 부여할 수 있다면,

오직 최대 1만개의 배열크기로 이를 해결할 수 있다.

 

 

아래에 소개하는 문제에서 좌표압축을 구현하기 위한 방법 중 1은 간단히 설명하고 실제 코드는 2로 보겠다.

1. stl의 map을 이용한 방법

  - 주어진 x 좌표들을 오름차순으로 정렬한다. (기존 x좌표 순서는 그대로 다른 배열에 copy)

  - cnt = 0부터 시작하여, 작은 x[i]부터 보면서

    map에 없다면 map[x[i]] = cnt++

    map에 있다면 map[x[i]] = cnt

  - 기존 x좌표의 순서대로 x값을 읽어오며 map[x[i]]의 값을 출력한다.

 

2. binary search, vector의 erase() + unique()를 이용한 방법

 기존의 x좌표들을 vector에 담아 오름차순으로 정렬하면

중복되는 x값이 없다고 가정했을 때 해당 x값을 담고 있는 vector의 index가 압축된 좌표가 된다.

 

예를 들어 문제에서 x = { 1000, 10, 100, 1, 10000}일 때,

이를 vector v에 담아서 오름차순으로 정렬하면 v = {1, 10, 100, 1000, 10000} 이고,

1의 압축된 좌표는 0,  10의 압축된 좌표는 1, 100의 압축된 좌표는 3 ... 이런 셈이다.

 

따라서 x의 값을 copy하여 vector에 담고, 이를 정렬해 정렬되지 않은 기존 x의 값을 하나하나 binary search를 통해 찾을 수 있다.

하지만 문제는, x의 값들이 중복해서 존재하는 것이고 binary search를 사용하기 위해 중복된 원소를 제거해야한다.

어떻게 하면 {0, 0, 1, 2, 3, 3, 4, 5, 5,} 와 같은 vector에서 중복된 원소를 없애 {0, 1, 2, 3, 4, 5}로 만들 수 있을까?

 

 

vector의 erase와 unique를 사용하면 간단하게 중복된 원소를 처리할 수 있다.

 

vcetor의 unique(first, last)는 정렬된 vector에서 중복된 원소(쓰레기 값)를 정렬된 데이터의 뒤로 보내고, 정렬된 데이터의 마지막 iterator의 다음 위치를 반환한다.

예를 들어, {1, 2, 2, 3, 3, 5, 6}의 vector는 unique를 통해 {1, 2, 3, 5, 2, 3, 6} 으로 바뀌고

정렬된 데이터의 마지막 원소인 5의 다음 위치인 2에 해당하는 iterator를 반환한다.

 

vector의 erase(first, last)는 vector의 first부터 last까지의 원소를 지워준다.

따라서 정렬된 v를 v.erase( unique(v.begin( ), v.end( )), v.end( ) )를 통해서 중복된 원소를 제거 할 수 있고,

binary search를 통해 기존 x의 압축된 index를 구할 수 있다.


소스코드

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

int n;
vector <int> x, y;
int main()
{
    scanf("%d", &n);
    x.resize(n);
    y.resize(n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &x[i]);
        y[i] = x[i];
    }
    sort(y.begin(), y.end());
    unique(y.begin(), y.end());
    y.erase(unique(y.begin(), y.end()), y.end());

    for (int i = 0; i < n; ++i) {
        int pos = lower_bound(y.begin(), y.end(), x[i]) - y.begin();
        printf("%d ", pos);
    }
    return 0;
}

 

 

 

 

 

공부한 것을 정리하기 위한 기록입니다.

틀린 부분이 있다면 언제나 부드럽게 알려주세요.

'PS > BOJ' 카테고리의 다른 글

[BOJ 1310] 달리기 코스  (0) 2020.08.26
[BOJ 16480] 외심과 내심은 사랑입니다  (0) 2020.07.28
[BOJ] 어른 상어  (0) 2020.06.09
[BOJ 19236] 청소년 상어  (0) 2020.06.09
[BOJ 14503] 로봇청소기  (0) 2020.05.15

댓글