티스토리 뷰
[BOJ 7469] K번째 수 - P3
문제 설명 :
문제 풀이 :
mergesort tree를 이용해서 풀 수 있다. megesort tree는 트리의 노드가 값 하나가 아니라, 원소 그 자체를 담고 있기 때문에 여러개의 원소를 담고 있을 수 있다. 마치 merge sort가 되는 과정을 tree화 시킨 것이라고 보면 된다.
그래서 이분탐색으로 mid값을 지정하여 [l,r]구간에 mid 이하의 값이 몇 개인지를 log 만에 찾을 수 있다.
배울 점 :
mergesort Tree를 이용하면 N개의 원소 중에서 [l,r]구간의 x보다 크거나 작은 원소의 개수를 log만에 구할 수 있다.
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
const int SIZE = 100009;
vector<int> tree[SIZE*8];
int startIdx=1;
void makeMergeSortTree(){
for(int i = startIdx - 1; i>=1 ; i--){
int lChild = i*2,rChild = i*2+1;
int lIdx = 0,rIdx = 0;
int sz = tree[lChild].size();
while(lIdx < sz && rIdx < sz){
if(tree[lChild][lIdx] > tree[rChild][rIdx]) tree[i].push_back(tree[rChild][rIdx++]);
else tree[i].push_back(tree[lChild][lIdx++]);
}
if(lIdx < sz){
for(int j = lIdx ; j < sz ; j++){
tree[i].push_back(tree[lChild][j]);
}
}
else for(int j = rIdx ; j < sz ; j++){
tree[i].push_back(tree[rChild][j]);
}
}
}
int query(int node,int cl, int cr,int ql,int qr,int x){
if(cl > qr || ql > cr) return 0;
if(qr >= cr && cl >= ql) {
int cnt = upper_bound(tree[node].begin(), tree[node].end(), x) - tree[node].begin() ;
return cnt;
}
int mid = (cl+cr)/2;
return query(node*2,cl,mid,ql,qr,x) + query(node*2+1,mid+1,cr,ql,qr,x);
}
int main(){
int n,q; scanf("%d %d",&n,&q);
for(; startIdx < n ; startIdx *= 2);
for(int i=1 ; i<=n ; i++){
int inp; scanf("%d",&inp);
tree[startIdx + i - 1].push_back(inp);
}
for(int i=startIdx+n ; i <= startIdx*2 ; i++){
tree[i].push_back(2e9);
}
makeMergeSortTree();
while(q--){
int ql,qr,x; scanf("%d %d %d",&ql,&qr,&x);
int l = -1e9-3,r = 1e9+3;
while(l+1 < r){
int mid = (l+r)/2;
if(query(1,1,startIdx,ql,qr,mid) >= x) r = mid;
else l = mid;
}
printf("%d\n",r);
}
return 0;
}
'Problem Solving > Segment Tree' 카테고리의 다른 글
[BOJ 11658]구간 합 구하기3 (0) | 2021.11.13 |
---|---|
[BOJ 2243] 사탕 상자, [BOJ 9426] 중앙값 측정 (0) | 2021.10.29 |
[BOJ 1517] 버블 소트 (0) | 2021.10.21 |
[CF 1042D] Petya and Array (0) | 2021.10.21 |
[BOJ 1725] 히스토그램 (0) | 2021.10.15 |
댓글