728x90
SMALL
백준 문제 풀이: 14427 [수열과 쿼리 15]
문제 링크: https://www.acmicpc.net/problem/14427
문제 설명:
주어진 수열에서 최소값과 그 인덱스를 빠르게 찾기 위해 세그먼트 트리를 사용하여 쿼리를 처리하는 문제입니다. 쿼리에는 다음 두 가지가 포함됩니다:
1 b c
: 수열의b
번째 값을c
로 변경합니다.2
: 현재 수열에서 최소값의 인덱스를 출력합니다. (동일한 값이 여러 개 있을 경우 인덱스가 작은 것을 출력)
문제 해결 코드
// 백준 14427 - 수열과 쿼리 15
#include <iostream>
#include <algorithm>
using namespace std;
struct SegTree {
int idx; // 최소값의 인덱스
int value; // 최소값
};
const int INF = 1e9 + 1;
SegTree seg[400001];
int arr[1000001];
// 세그먼트 트리 초기화
SegTree build(int node, int start, int end) {
if (start == end) {
seg[node] = {start, arr[start]};
return seg[node];
}
int mid = (start + end) / 2;
SegTree left = build(node * 2, start, mid);
SegTree right = build(node * 2 + 1, mid + 1, end);
if (left.value < right.value || (left.value == right.value && left.idx < right.idx)) {
seg[node] = left;
} else {
seg[node] = right;
}
return seg[node];
}
// 세그먼트 트리 업데이트
SegTree update(int node, int start, int end, int index, int newValue) {
if (index < start || index > end) return seg[node];
if (start == end) {
seg[node] = {start, newValue};
return seg[node];
}
int mid = (start + end) / 2;
SegTree left = update(node * 2, start, mid, index, newValue);
SegTree right = update(node * 2 + 1, mid + 1, end, index, newValue);
if (left.value < right.value || (left.value == right.value && left.idx < right.idx)) {
seg[node] = left;
} else {
seg[node] = right;
}
return seg[node];
}
// 세그먼트 트리에서 전체 최소값 찾기
SegTree query(int node, int start, int end, int left, int right) {
if (right < start || left > end) return {INF, INF};
if (left <= start && end <= right) return seg[node];
int mid = (start + end) / 2;
SegTree leftResult = query(node * 2, start, mid, left, right);
SegTree rightResult = query(node * 2 + 1, mid + 1, end, left, right);
if (leftResult.value < rightResult.value || (leftResult.value == rightResult.value && leftResult.idx < rightResult.idx)) {
return leftResult;
} else {
return rightResult;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
build(1, 0, n - 1);
cin >> m;
for (int i = 0; i < m; i++) {
int type;
cin >> type;
if (type == 1) {
int b, c;
cin >> b >> c;
b--;
arr[b] = c;
update(1, 0, n - 1, b, c);
} else if (type == 2) {
cout << query(1, 0, n - 1, 0, n - 1).idx + 1 << '\n';
}
}
return 0;
}
코드 설명
코드의 주요 로직과 사용된 알고리즘 설명.
- 핵심 알고리즘: 세그먼트 트리를 사용하여 최소값과 그 인덱스를 효율적으로 관리합니다.
- 구현 세부사항:
build
: 초기 세그먼트 트리를 구축합니다.update
: 배열 값을 변경할 때 세그먼트 트리를 갱신합니다.query
: 현재 배열에서 전체 구간의 최소값과 인덱스를 반환합니다.
- 시간 복잡도 분석:
- 세그먼트 트리 구축: O(n)
- 쿼리 및 업데이트: O(log n)
- 총 시간 복잡도: O((n + m) log n)
결과
제출 시, 모든 테스트 케이스에 대해 올바른 결과를 출력합니다.
다른 접근 방식이나 개선 사항이 있다면 댓글로 공유 부탁드립니다!
728x90
LIST
'BAEKJOON > 자료 구조' 카테고리의 다른 글
백준 1764번 [듣보잡](C++) -yes6686- 티스토리 (0) | 2024.12.24 |
---|---|
백준 1620번 [나는야 포켓몬 마스터 이다솜](C++) -yes6686- 티스토리 (0) | 2024.12.24 |
백준 27497번 [알파벳 블록](C++) -yes6686- 티스토리 (0) | 2024.07.13 |
백준 25957번 [단어 우월 효과 (캠브릿지 대학의 연구결과)](C++) -yes6686- 티스토리 (0) | 2024.05.10 |
백준 2295번 [세 수의 합](C++) -yes6686- 티스토리 (0) | 2024.05.10 |