백준 7469번 K번째 수
문제 링크입니다: https://www.acmicpc.net/problem/7469
좌표 압축과 퍼시스턴트 세그먼트 트리를 이용하는 문제였습니다.
퍼시스턴트 세그먼트 트리 관련해서는 justicehui님 블로그를 참고하시면 될 것 같습니다.
https://justicehui.github.io/medium-algorithm/2020/02/29/PST/
알고리즘은 다음과 같습니다.
1. 배열 a의 값들이 [-10^9, 10^9] 범위를 갖기 때문에 세그먼트 트리의 인덱스로 직접 쓰기에는 범위가 너무 광범위합니다.
1.1 이에 따라 배열 값들을 정렬 후 중복 제거하여 좌표 압축을 진행해야 합니다.
1.2 compArr[i]는 a[i]의 압축된 값 즉, 1부터 시작하는 인덱스 값을 저장합니다.
2. 퍼시스턴트 세그먼트 트리를 구성합니다.
2.1 root[i]는 `배열의 앞에서부터 i 번째 원소까지 반영된 세그먼트 트리`의 루트 노드입니다.
2.2 root[0]은 아무 원소도 반영되지 않은 빈 세그먼트 트리로 구성합니다.
2.3 이후 i 번째 원소를 삽입할 때마다 이전 버전 root[i - 1]을 복사하면서 새로운 좌표(압축값 인덱스)만 +1 해줍니다.
2.4 퍼시스턴트 세그먼트 트리이기 때문에 새 노드는 필요한 부문만 복사하며 전체 트리를 중복해서 만들지 않습니다.
3. 쿼리 Q(i, j, k)를 계산하고 출력합니다.
3.1 root[j]와 root[i - 1] 두 버전을 비교하면 구간 [i, j]에 들어 있는 원소들의 빈도 정보를 얻을 수 있습니다.
3.2 세그먼트 트리를 내려가면서 `왼쪽 자식에 몇 개가 있는가`를 확인해 k를 조정해 나가는 방식으로 k 번째 원소의 압축값을 찾은 뒤 해당 압축값을 원래 값으로 되돌려 출력합니다.
개발환경:Visual Studio 2017
지적, 조언, 질문 환영입니다! 댓글 남겨주세요~