문제
N(1 ≤ N ≤ 100,000)개의 정수들이 있을 때, a번째 정수부터 b번째 정수까지 중에서 제일 작은 정수, 또는 제일 큰 정수를 찾는 것은 어려운 일이 아니다. 하지만 이와 같은 a, b의 쌍이 M(1 ≤ M ≤ 100,000)개 주어졌을 때는 어려운 문제가 된다. 이 문제를 해결해 보자.
여기서 a번째라는 것은 입력되는 순서로 a번째라는 이야기이다. 예를 들어 a=1, b=3이라면 입력된 순서대로 1번, 2번, 3번 정수 중에서 최소, 최댓값을 찾아야 한다. 각각의 정수들은 1이상 1,000,000,000이하의 값을 갖는다.
입력
첫째 줄에 N, M이 주어진다. 다음 N개의 줄에는 N개의 정수가 주어진다. 다음 M개의 줄에는 a, b의 쌍이 주어진다.
출력
M개의 줄에 입력받은 순서대로 각 a, b에 대한 답을 최솟값, 최댓값 순서로 출력한다.
풀이 과정
최솟값과 최댓값 세그먼트 트리를 만들어 풀이했다.
#include <stdio.h>
int arr[100000];
int min_tree[400000];
int max_tree[400000];
int min_init(int start, int end, int idx) {
if (start == end) {
min_tree[idx] = arr[start];
return min_tree[idx];
}
int mid = (start + end) / 2;
int n1 = min_init(start, mid, idx * 2);
int n2 = min_init(mid + 1, end, idx * 2 + 1);
if (n1 < n2) min_tree[idx] = n1;
else min_tree[idx] = n2;
return min_tree[idx];
}
int max_init(int start, int end, int idx) {
if (start == end) {
max_tree[idx] = arr[start];
return max_tree[idx];
}
int mid = (start + end) / 2;
int n1 = max_init(start, mid, idx * 2);
int n2 = max_init(mid + 1, end, idx * 2 + 1);
if (n1 > n2) max_tree[idx] = n1;
else max_tree[idx] = n2;
return max_tree[idx];
}
int find_min(int start, int end, int idx, int left, int right) {
if (end < left || right < start) return -1;
if (left <= start && end <= right) return min_tree[idx];
int mid = (start + end) / 2;
int n1 = find_min(start, mid, idx * 2, left, right);
int n2 = find_min(mid + 1, end, idx * 2 + 1, left, right);
if (n1 == -1 || n2 == -1) {
if (n1 != -1) return n1;
else if (n2 != -1) return n2;
else return -1;
}
else {
if (n1 < n2) return n1;
else return n2;
}
}
int find_max(int start, int end, int idx, int left, int right) {
if (end < left || right < start) return -1;
if (left <= start && end <= right) return max_tree[idx];
int mid = (start + end) / 2;
int n1 = find_max(start, mid, idx * 2, left, right);
int n2 = find_max(mid + 1, end, idx * 2 + 1, left, right);
if (n1 == -1 || n2 == -1) {
if (n1 != -1) return n1;
else if (n2 != -1) return n2;
else return -1;
}
else {
if (n1 > n2) return n1;
else return n2;
}
}
int main(void) {
int n, m;
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++) scanf("%d", &arr[i]);
min_init(0, n - 1, 1);
max_init(0, n - 1, 1);
for (int i = 0; i < m; i++) {
int a, b;
scanf("%d %d", &a, &b);
printf("%d %d\n", find_min(0, n - 1, 1, a - 1, b - 1), find_max(0, n - 1, 1, a - 1, b - 1));
}
return 0;
}
'-- 예전 기록 > BOJ' 카테고리의 다른 글
[ BOJ ] 15686 : 치킨 배달 ( GOLD 5 ) / Python (0) | 2023.03.24 |
---|---|
[ BOJ ] 1275 : 커피숍2 ( GOLD 1 ) / C (0) | 2023.03.16 |
[ BOJ ] 11143 : Beads ( GOLD 1 ) / C (0) | 2023.03.16 |
[ BOJ ] 16975 : 수열과 쿼리 21 ( PLATINUM 4 ) / C (1) | 2023.03.16 |
[ BOJ ] 10999 : 구간 합 구하기 2 ( PLATINUM 4 ) / C (1) | 2023.03.16 |