https://www.acmicpc.net/problem/2517
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
'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 |