[백준 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
댓글을 사용할 수 없습니다.