[백준 2357번 C/C++] 최솟값과 최댓값
[백준 2357번 C/C++] 최솟값과 최댓값
https://www.acmicpc.net/problem/2357
2357번: 최솟값과 최댓값
N(1 ≤ N ≤ 100,000)개의 정수들이 있을 때, a번째 정수부터 b번째 정수까지 중에서 제일 작은 정수, 또는 제일 큰 정수를 찾는 것은 어려운 일이 아니다. 하지만 이와 같은 a, b의 쌍이 M(1 ≤ M ≤ 100
www.acmicpc.net
해결전략
세크먼트 트리 Segment Tree
자료 구조
정답코드
#include <iostream>
#include <vector>
#include <cmath> // ceil, log2, min, max에 필요
using namespace std;
#define INF 1000000001
struct Value{
long long minNum, maxNum;
};
int n, m;
vector<int> v;
vector<Value> sTree;
Value SegmentTree(int node, int start, int end)
{
if (start == end) { // node가 leaf node인 경우
sTree[node].minNum = v[start];
sTree[node].maxNum = v[start];
return sTree[node];
}
int mid = (start + end) / 2;
Value left = SegmentTree(node * 2, start, mid);
Value right = SegmentTree(node * 2 + 1, mid + 1, end);
sTree[node].minNum = min(left.minNum, right.minNum);
sTree[node].maxNum = max(left.maxNum, right.maxNum);
return sTree[node];
}
Value FindMinMax(int node, int start, int end, int left, int right)
{
if (left > end || right < start) {
return Value{ INF, 0 };
}
if (left <= start && end <= right){
return sTree[node];
}
int mid = (start + end) / 2;
Value tempLeft = FindMinMax(node * 2, start, mid, left, right);
Value tempRight = FindMinMax(node * 2 + 1, mid + 1, end, left, right);
Value result;
result.minNum = min(tempLeft.minNum, tempRight.minNum);
result.maxNum = max(tempLeft.maxNum, tempRight.maxNum);
return result;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m;
v.resize(n);
for(int i = 0; i < n; i++){
cin >> v[i];
}
int treeHeight = (int)ceil(log2(n));
int treeSize = (1 << (treeHeight + 1));
sTree.resize(treeSize);
SegmentTree(1, 0, n - 1);
for(int i = 0; i < m; i++){
int a, b;
cin >> a >> b;
Value tmp = FindMinMax(1, 0, n - 1, a-1, b-1);
cout << tmp.minNum << " " << tmp.maxNum << "\n";
}
return 0;
}
주석
#include <iostream>
#include <vector>
#include <cmath> // ceil, log2, min, max에 사용
using namespace std;
#define INF 1000000001
struct Value{ // 세그먼트 트리의 각 노드에 저장될 구조체
long long minNum, maxNum;
};
int n, m; // n은 입력값의 개수, m은 쿼리의 개수
vector<int> v; // 입력값을 저장할 벡터
vector<Value> sTree; // 세그먼트 트리
// 세그먼트 트리를 구성하는 함수. 재귀적으로 호출되며, 각 노드에는 해당 범위의 최소값과 최대값이 저장됨.
Value SegmentTree(int node, int start, int end)
{
if (start == end) { // node가 leaf node인 경우
sTree[node].minNum = v[start];
sTree[node].maxNum = v[start];
return sTree[node];
}
int mid = (start + end) / 2;
Value left = SegmentTree(node * 2, start, mid); // 왼쪽 자식 노드를 구성
Value right = SegmentTree(node * 2 + 1, mid + 1, end); // 오른쪽 자식 노드를 구성
sTree[node].minNum = min(left.minNum, right.minNum); // 왼쪽 자식 노드와 오른쪽 자식 노드의 최소값 중 작은 값을 저장
sTree[node].maxNum = max(left.maxNum, right.maxNum); // 왼쪽 자식 노드와 오른쪽 자식 노드의 최대값 중 큰 값을 저장
return sTree[node];
}
// 주어진 범위 [left, right]에서 최소값과 최대값을 찾는 함수.
Value FindMinMax(int node, int start, int end, int left, int right)
{
if (left > end || right < start) {
return Value{ INF, 0 }; // 범위 밖인 경우, minNum은 INF, maxNum은 0으로 설정
}
if (left <= start && end <= right){
return sTree[node]; // 범위 안에 전체가 포함되는 경우, 해당 노드의 값을 반환
}
int mid = (start + end) / 2;
Value tempLeft = FindMinMax(node * 2, start, mid, left, right); // 왼쪽 자식 노드에서 찾기
Value tempRight = FindMinMax(node * 2 + 1, mid + 1, end, left, right); // 오른쪽 자식 노드에서 찾기
Value result;
result.minNum = min(tempLeft.minNum, tempRight.minNum); // 왼쪽과 오른쪽에서 찾은 최소값 중 작은 값을 저장
result.maxNum = max(tempLeft.maxNum, tempRight.maxNum); // 왼쪽과 오른쪽에서 찾은 최대값 중 큰 값을 저장
return result;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m;
v.resize(n);
for(int i = 0; i < n; i++){
cin >> v[i];
}
int treeHeight = (int)ceil(log2(n)); // 세그먼트 트리의 높이 계산
int treeSize = (1 << (treeHeight + 1)); // 세그먼트 트리의 크기 계산
sTree.resize(treeSize); // 세그먼트 트리의 크기를 설정
SegmentTree(1, 0, n - 1); // 세그먼트 트리 구성
for(int i = 0; i < m; i++){
int a, b;
cin >> a >> b; // 쿼리 범위
Value tmp = FindMinMax(1, 0, n - 1, a-1, b-1); // 쿼리 범위에서 최소값과 최대값을 찾음
cout << tmp.minNum << " " << tmp.maxNum << "\n";
}
return 0;
}
'⭐ 코딩테스트 > 백준' 카테고리의 다른 글
[백준 13141번 C/C++] Ignition (0) | 2024.03.12 |
---|---|
[백준 13977번 C/C++] 이항 계수와 쿼리 (0) | 2024.03.08 |
[백준 14517번 C/C++] 팬린드롬 개수 (1) | 2024.02.26 |
[백준 2533번 C/C++] 사회망 서비스(SNS) (0) | 2024.02.22 |
[백준 1094번 C/C++] 막대기 (0) | 2024.02.17 |
댓글
이 글 공유하기
다른 글
-
[백준 13141번 C/C++] Ignition
[백준 13141번 C/C++] Ignition
2024.03.12 -
[백준 13977번 C/C++] 이항 계수와 쿼리
[백준 13977번 C/C++] 이항 계수와 쿼리
2024.03.08 -
[백준 14517번 C/C++] 팬린드롬 개수
[백준 14517번 C/C++] 팬린드롬 개수
2024.02.26 -
[백준 2533번 C/C++] 사회망 서비스(SNS)
[백준 2533번 C/C++] 사회망 서비스(SNS)
2024.02.22