백준

/<> 백준 18870번 : 좌표 압축 (C언어)

모나오랭 2024. 8. 31. 16:29

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

 

 

문제에서 주의할 점은, 숫자의 중복을 허용하지 않는다는 점입니다. 따라서 입력받는 수 중 중복되는 수들을 카운트할 때 제외해야 합니다. 

 

 

1. 숫자를 저장할 배열 2개를 생성하여, 하나는 마지막 크기 비교용, 하나는 순서 정렬용으로 사용합니다.

 

2. qsort를 사용해 한 배열을 정렬합니다.

 

3. 중복을 없애기 위해 2단계를 토대로 숫자 종류가 하나씩만 있는 배열을 생성합니다.

 

4. 처음에 만든 나머지 배열을 3단계의 배열과 비교하여 자기보다 작은 숫자가 몇 개인지 비교합니다. 이때 시간복잡도를 줄이기 위해 이진 탐색을 사용합니다.

 

 

<코드>

#include <stdio.h>
#include <stdlib.h>

int compare(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}

int main() {
    int n;
    scanf("%d", &n);
    int num[n];
    int num2[n];
    int unique[n];
    int count[n];
    
    for(int i = 0; i < n; i++) count[i] = 0;
    for(int i = 0; i < n; i++) {
        scanf("%d", &num[i]);
        num2[i] = num[i];
    }

    qsort(num, n, sizeof(int), compare);

    // 고유한 숫자 배열 생성
    int idx = 0;
    unique[idx++] = num[0];
    for(int i = 1; i < n; i++) {
        if(num[i] != num[i-1]) {
            unique[idx++] = num[i];
        }
    }

    // 각 숫자보다 큰 고유 숫자의 개수를 계산
    for(int i = 0; i < n; i++) {
        int left = 0, right = idx - 1, mid;
        while(left <= right) {
            mid = (left + right) / 2;
            if(num2[i] > unique[mid]) left = mid + 1;
            else right = mid - 1;
        }
        count[i] = left;
    }

    for(int i = 0; i < n; i++) printf("%d ", count[i]);
    printf("\n");

    return 0;
}

 

 

풀면서 계속 시간 초과가 떴던 문제였습니다. qsort와 이진 탐색을 잘 활용해야겠습니다.