코딩테스트

백준 10431 줄세우기 ( set, bst 활용 )

코앤미 2025. 2. 19. 15:52

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

 

매번 줄을 설 때마다 자기보다 키가 큰 학생 수를 더하면 밀려난 총량이 나온다.

따라서, 기존에 줄을 선 아이들 중, 이번에 줄을 설 아이보다 키가 큰 아이의 수를 찾으면된다.

이걸 O(N)으로 탐색해도 input 이 크지 않기에 상관 없지만, BST를 구축하면 O(logN)만에 찾을 수 있기에 BST를 사용할 것이다.

추가로, vector를 써도 되지만, vector는 매번 줄을 선아이를 추가하는 insert에서 O(N)의 시간 복잡도가 든다.

 

따라서, 문제의 튜닝 포인트는 아래와 같다

1) BST를 통해 자신보다 큰 아이의 개수를 찾기

lower_bound & upper_bound 라이브러리는 bst 기반 탐색으로 자기보다 큰 키의 아이들을 찾으면 된다.

 

lower_bound

찾고자 하는 값보다 같거나 큰 숫자 처음 등장하는 위치 반환

  • 용도 1 : key 값이 가장 처음 등장하는 위치 찾을 때
  • 용도 2 : key 값보다 작은 값들의 개수 구할 때

upper_bound

찾고자 하는 값을 초과하는 값 가장 처음 나타나는 위치를 반환

  • 용도 1 : key 값이 가장 마지막에 등장하는 위치 찾을 때
  • 용도 2 : key 값보다 큰 값들의 개수 구할 때

 

2)  문제 조건에서 키는 중복되지 않는다는 조건과 부합하기도 하고, insert cost가 O(logN) 인 set에 줄을 선 아이들 정보를 누적한다.

 

정답

#include <string>
#include <vector>
#include<iostream>
#include<set>
using namespace std;


const int NUM = 20;


int main(){
   // 1명씩 뒤로 서는 과정에서, 물러나는 총 개수 (  물러난 사람 * 물러난 양)
    int t;
    cin>>t;
    while(t--){
        int arr[20];
        int testNum;
        cin>>testNum;
        
        for(int n=0;n<NUM;n++){
            cin>>arr[n];
        }
        set<int> sortedNumbers;
        int answer =0;
        for(auto h: arr){
            auto it = sortedNumbers.upper_bound(h);
            int tallerNum = distance(it, sortedNumbers.end());
            answer += tallerNum;
            sortedNumbers.insert(h);
        }
        cout<<testNum<<" "<<answer<<endl;
    }
}