문제 링크
풀이
세그먼트 트리를 이용하여 k번째 수를 가져오는 문제이다.
세그먼트 트리를 만들 때 수의 범위가 아닌 수의 값으로 범위를 정해야 한다.
예를 들어, 5번째 수를 구할 때, 1 ~ N/2에 수가 6개 N/2 + 1 ~ N에 수가 3개가 있다고 한다면 왼쪽 노드로 이동하여 같은 작업을 반복해야 한다. 반면에 1 ~ N/2에 수가 2개 N/2 + 1 ~ N에 수가 5개가 있다고 하면, 오른쪽 노드로 이동하여 5-2인 3번째 수를 구해야 한다.
코드
#include <cstdio>
const int MAX = 2e6;
int tree[MAX * 4 + 6];
int query(int node, int s, int e, int k) {
tree[node]--;
if (s == e) return s;
int mid = (s + e) >> 1;
if (tree[2 * node] >= k) return query(2 * node, s, mid, k);
else return query(2 * node + 1, mid + 1, e, k - tree[2 * node]);
}
void update(int node, int s, int e, int idx) {
if (idx < s || e < idx) return;
tree[node]++;
if (s == e) return;
int mid = (s + e) >> 1;
update(2 * node, s, mid, idx);
update(2 * node + 1, mid + 1, e, idx);
}
int main() {
int n; scanf("%d", &n);
while (n--) {
int s, x; scanf("%d %d", &s, &x);
if (s == 1) {
update(1, 1, MAX, x);
} else {
printf("%d\n", query(1, 1, MAX, x));
}
}
}
'Algorithm > BOJ' 카테고리의 다른 글
백준[2170] 선 긋기 (0) | 2021.08.20 |
---|---|
백준[1168] 요세푸스 문제 2 (0) | 2021.08.19 |
백준[16975] 수열과 쿼리 21 (0) | 2021.08.16 |
백준[9345] 디지털 비디오 디스크(DVDs) (0) | 2021.08.15 |
백준[1517] 버블 소트 (0) | 2021.08.11 |