Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 데이터 분석
- Cloud Pub/Sub
- BFS
- 삼성 SW 역량테스트
- Air Table
- 수학
- 우선순위 큐
- jpa
- Cloud Run
- r
- 다이나믹 프로그래밍
- 펜윅 트리
- CI/CD
- ICPC
- 시뮬레이션
- Bit
- LCS
- 고속 푸리에 변환
- 컴퓨터 구조
- JavaScript
- 다익스트라
- 생활코딩
- 그리디
- REACT
- 접미사 배열
- 백준 1753번
- dp
- 삼성SW역량테스트
- 이분탐색
- 종만북
Archives
- Today
- Total
코딩스토리
백준 2357번 - 최솟값과 최댓값 본문
https://www.acmicpc.net/problem/2357
풀이
Min, Max Segment Tree를 사용한 문제이다.
Min, Max Segment Tree란 각 범위의 최소값과 최대값을 가지고 있는 세그먼트 트리를 말한다.
두 개의 세그먼트 트리를 만들 수도 있지만 코드가 길어질 것 같아서 pair를 사용해 하나의 트리로 만들었다.
구현은 일반적인 세그트리와 비슷하다.
세그트리 자체를 이해했다면 이 코드 역시 이해하기 어렵지 않을 것이다.
참고로 비슷하게 짰는데 시간초과가 난다면 아래의 코드를 붙여서 돌려보면 통과할 수도 있다!
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
const int INF = INT_MAX;
vector<ll>arr(100007);
vector<pll>MinMaxTree(300007); // min = first, max = second
pll init(int node, int start, int end) {
if (start == end) { // 리프 노드
return MinMaxTree[node] = pll(arr[start], arr[start]);
}
else {
pll left = init(node * 2, start, (start + end) / 2), right = init(node * 2 + 1, (start + end) / 2 + 1, end);
return MinMaxTree[node] = pll(min(left.first, right.first), max(left.second, right.second));
}
}
pll query(int node, int start, int end, int left, int right) {
if (end < left || right < start) return pll(INF, 0);
if (left <= start && end <= right) return MinMaxTree[node];
pll l = query(node * 2, start, (start + end) / 2, left, right), r = query(node * 2 + 1, (start + end) / 2 + 1, end, left, right);
return pll(min(l.first, r.first), max(l.second, r.second));
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int n, m, a, b;
cin >> n >> m;
for (int i = 0; i < n; i++) cin >> arr[i];
init(1, 0, n - 1);
for (int i = 0; i < m; i++) {
cin >> a >> b;
pll ans = query(1, 0, n - 1, a - 1, b - 1);
cout << ans.first << " " << ans.second << "\n";
}
}
update는 이 문제에서 나오지 않았지만 다른 난이도 있는 문제를 풀 때에는 update 함수가 꼭 필요할 것이다.
아래는 index번째 수를 num으로 교체하기 위해 사용할 수 있는 update에 대해 구현한 것이다.
pll update(int node, int start, int end, int index, ll num) {
if (index < start || end < index) return MinMaxTree[node];
if (start == end) MinMaxTree[node] = pll(num, num);
else {
pll left = update(node * 2, start, (start + end) / 2, index, num);
pll right = update(node * 2 + 1, (start + end) / 2 + 1, end, index, num);
MinMaxTree[node].first = min(left.first, right.first);
MinMaxTree[node].second = max(left.second, right.second);
}
return MinMaxTree[node];
}
만약 update 해야 하는 범위에 속하지 않는다면 건너뛰고
포함된다면 리프 노드인지 아닌지에 따라 update하면 된다.
그림을 그려보면서 이해하는걸 추천한다.
'알고리즘 > BOJ 문제 풀이' 카테고리의 다른 글
백준 1135번 - 뉴스 전하기 (0) | 2021.09.02 |
---|---|
백준 16566번 - 카드 게임 (0) | 2021.07.07 |
백준 2517번 - 달리기 (0) | 2021.06.19 |
백준 2042번 - 구간 합 구하기 (0) | 2021.05.28 |
백준 14289번 - 본대 산책 3 (0) | 2021.05.22 |
Comments