728x90
반응형
[세그먼트 트리] 세그먼트 트리 알고리즘 정리
📌 세그먼트 트리란?
세그먼트 트리는 배열의 구간 정보를 저장하여 구간 쿼리와 업데이트를 효율적으로 처리하는 자료구조입니다. 주로 구간 합, 최소값, 최대값 등을 O(log n) 시간 안에 계산할 수 있도록 도와줍니다.
🚨 세그먼트 트리의 구조
- 완전 이진 트리: 배열을 기반으로 한 완전 이진 트리 구조로 구현됩니다.
- 노드 역할:
- 리프 노드: 배열의 개별 원소를 저장합니다.
- 내부 노드: 자식 노드의 값을 이용해 해당 구간의 정보를(예, 최소값 또는 합) 계산해 저장합니다.
💡 주요 연산
- 구간 쿼리: 특정 구간(예, [L, R])의 합 또는 최소/최대값을 O(log n) 시간 내에 계산할 수 있습니다.
- 업데이트: 배열의 한 원소가 변경되었을 때, O(log n) 시간 안에 트리 전체에 반영할 수 있습니다.
Tip:
리프 노드의 개수를 “N 이상의 최소 2의 거듭제곱”으로 맞추면, 트리의 높이가 일정해지고 인덱스 계산이 단순해집니다.
(예: leaf_start = 2**math.ceil(math.log2(N)))
📚 예제 코드 (구간 최소값)
아래 코드는 구간 최소값을 구하는 세그먼트 트리의 구현 예제입니다. (구간 합 쿼리 및 업데이트 구현도 유사한 방식으로 작성할 수 있습니다.)
import math
def build_min_tree(arr):
n = len(arr)
# 리프 노드 시작 인덱스: n 이상의 최소 2의 거듭제곱
leaf_start = 2 ** math.ceil(math.log2(n))
tree_size = 2 * leaf_start
# 구간 최소값을 위한 초기값은 무한대로 설정
tree = [float('inf')] * tree_size
# 리프 노드에 배열 값 채워넣기
tree[leaf_start:leaf_start + n] = arr[:]
# 내부 노드 채우기: 자식 노드의 최소값으로 부모 노드 결정
for i in range(leaf_start - 1, 0, -1):
tree[i] = min(tree[2 * i], tree[2 * i + 1])
return tree, leaf_start
def update_min_tree(tree, leaf_start, index, value):
# index: 원본 배열의 0-based 인덱스
pos = leaf_start + index
tree[pos] = value
pos //= 2
while pos >= 1:
tree[pos] = min(tree[2 * pos], tree[2 * pos + 1])
pos //= 2
def query_min_tree(tree, leaf_start, query_left, query_right):
# query_left, query_right: 0-based 인덱스로 구간 지정
left = leaf_start + query_left
right = leaf_start + query_right
result = float('inf')
while left <= right:
if left % 2 == 1:
result = min(result, tree[left])
left += 1
if right % 2 == 0:
result = min(result, tree[right])
right -= 1
left //= 2
right //= 2
return result
예제 실행
if name == 'main':
arr = [5, 3, 8, 6, 2, 7, 4]
tree, leaf_start = build_min_tree(arr)
# 인덱스 1~5 구간의 최소값 조회 (0-based 인덱스)
print("초기 구간 최소값 (인덱스 1~5):", query_min_tree(tree, leaf_start, 1, 5))
# 인덱스 3의 값을 1로 업데이트
update_min_tree(tree, leaf_start, 3, 1)
print("업데이트 후 구간 최소값 (인덱스 1~5):", query_min_tree(tree, leaf_start, 1, 5))
🎯 세그먼트 트리의 핵심 포인트
- 효율적인 구간 쿼리: O(log n) 시간 내에 구간 정보를 조회할 수 있습니다.
- 빠른 업데이트: 특정 원소의 변경 사항이 O(log n) 시간 내에 트리에 반영됩니다.
- 메모리 사용: 트리 전체는 일반적으로 O(n) 공간을 사용합니다.
✨ 스터디를 통해 얻은 인사이트
- 구조와 동작 원리: 리프 노드부터 시작해 내부 노드를 채워 나가는 방식과 인덱스 계산 방식을 이해했습니다.
- 실제 문제 적용: 세그먼트 트리를 활용하여 구간 쿼리 문제를 효율적으로 해결할 수 있는 가능성을 확인했습니다.
- 코드 최적화: 메모리 관리 및 연산 효율성을 고려한 구현 방법에 대해 배웠습니다.
🔍 코드 설명
- build_min_tree
입력 배열을 기반으로 세그먼트 트리를 구성합니다.- 리프 노드를 “n 이상의 최소 2의 거듭제곱” 크기로 할당하여, 인덱스 계산을 단순화합니다.
- 내부 노드는 자식 노드의 최소값으로 채워집니다.
- update_min_tree
배열의 특정 인덱스 값을 업데이트한 후, 부모 노드들에 변경 사항을 전파합니다. - query_min_tree
주어진 구간 내의 최소값을 효율적으로 계산합니다.
이 글이 세그먼트 트리의 원리와 구현 방법을 이해하는 데 도움이 되길 바랍니다.
세그먼트 트리는 다양한 문제 상황에서 강력한 도구가 될 수 있으니, 여러 문제에 직접 적용해 보며 익혀보세요!
728x90
반응형
'알고리즘 스터디 정리(복습용)' 카테고리의 다른 글
[Python] 에라토스테네스의 체 (소수 구하기) (0) | 2025.03.07 |
---|
댓글