cs
CS/PS

[BOJ] 2517번 : 달리기

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

 

2517번: 달리기

첫째 줄에는 선수의 수를 의미하는 정수 N이 주어진다. N은 3 이상 500,000 이하이다. 이후 N개의 줄에는 정수가 한 줄에 하나씩 주어진다. 이 값들은 각 선수들의 평소 실력을 앞에서 달리고 있는

www.acmicpc.net

2012년도 정올 고등부 2번 문제다. segment tree와 좌표압축을 사용하면 된다.

 

실력을 기준으로 segment tree를 만들면 특정 실력의 선수를 확인할 때 O(logN)만에 최대 등수를 확인할 수 있다는 아이디어를 얻을 수 있다. 여기서 중요한 점은 앞에서부터 차례로 update를 해 주고 query를 처리하여서 i번째 선수까지만 tree에 반영이 될 수 있도록 하는 것이다.

 

이런 아이디어의 문제점은 실력이 10억 이하의 자연수로 제시된다는 점이다. 이 경우 실력 값을 기준으로 tree를 구축하면 space complexity의 조건을 만족하지 못한다. 따라서 n의 최대값이 50만이라는 점을 이용하여 좌표압축을 해 주어야 한다. 좌표압축을 시행하면 실력이 최대 50만으로 나타내어지므로 tree에 손쉽게 넣을 수 있다. 좌표압축은 다음과 같이 수행할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void coordCompress(int n) {
    vector<int> tempVec;
    map<int,int> contAbility;
    
    tempVec.resize(player.size());
    copy(player.begin(),player.end(),tempVec.begin());
    sort(tempVec.begin(),tempVec.end());
    
    int temp=1;
    contAbility.insert(make_pair(tempVec[0],1));
    for(int i =1; i<n; i++) {
        if(tempVec[i]>tempVec[i-1]) temp++;
        contAbility.insert(make_pair(tempVec[i],temp));
    }
    for(int i =0; i<n; i++)    player[i]=contAbility[player[i]];
}
cs

 

실력 값을 입력받은 player 벡터를 tempVec에 복사한 다음, tempVec을 정렬하고 map으로 매핑시킨다. 이것으로 player 값을 좌표압축 할 수 있다.

나머지는 간단하다. for문 하나로 query와 update를 순서대로 수행해 주면 된다.

 

1
2
3
4
for(int i =0; i<n; i++) {
        cout<<i-query(1,n,1,1,player[i])+1<<'\n';
        update(1,n,1,player[i]);
    }
cs

 

 

전체 코드는 내 github에서 확인할 수 있다.

 

 

 

https://github.com/Jordano-Jackson/PS/blob/main/BOJ/2517/2517.cpp

 

GitHub - Jordano-Jackson/PS: Problem solving

Problem solving. Contribute to Jordano-Jackson/PS development by creating an account on GitHub.

github.com

 

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

[BOJ] 2473번 : 세 용액  (0) 2021.07.31
[BOJ] 7578번 : 공장  (0) 2021.07.29
[BOJ] 10868번 : 최솟값  (0) 2021.07.24
[BOJ] 1781번 : 컵라면  (0) 2021.07.20
[BOJ] 1462번 : 퀴즈쇼  (0) 2021.07.14