출시·고도화 중
Algorithm
구간 트리(세그먼트 트리)는 배열의 구간 합·최솟값 질의와 값 갱신을 모두 O(log n)에 처리하는 자료 구조로, 펜윅 트리와 함께 코딩 테스트의 단골 주제입니다.
구간 트리(세그먼트 트리)는 배열을 반씩 나눈 구간마다 합, 최솟값, 최댓값 같은 요약 값을 저장해 두는 이진 트리입니다. 루트는 배열 전체를, 리프는 원소 하나를 맡고, 내부 노드는 두 자식의 값을 합친 값을 가집니다. 덕분에 어떤 연속 구간에 대한 질문이든 노드 몇 개를 합쳐서 답할 수 있습니다.
누적 합은 구간 합을 O(1)에 구하지만 원소 하나가 바뀌면 O(n)이 들고, 배열을 그대로 두면 갱신은 빠르지만 질의가 O(n)입니다. 구간 트리는 점 갱신과 구간 질의를 모두 O(log n)에 처리하므로, 값이 계속 바뀌면서 구간 질문이 쏟아지는 상황에 알맞습니다. 지연 전파를 더하면 구간 전체에 값을 더하는 구간 갱신도 O(log n)에 처리할 수 있습니다.
먼저 누적 합의 한계를 이해한 뒤, 작은 배열로 트리를 손으로 그려 보며 질의와 갱신이 어떤 노드를 지나는지 따라가 보는 것이 좋습니다. 이어서 짧은 반복문 구현과 펜윅 트리를 직접 작성하고, 구간 최솟값, 역순 쌍 세기, 구간 더하기 같은 대표 문제로 연습하면 코딩 테스트에서 바로 쓸 수 있습니다.
각 노드가 배열의 한 구간을 맡아 합이나 최솟값을 저장하며, 결합 법칙을 만족하고 항등원이 있는 연산이면 무엇이든 담을 수 있습니다.
원소 하나를 바꾸면 리프에서 루트까지 한 경로만 다시 계산하고, 구간 질의는 층마다 많아야 두 노드를 합쳐 답합니다.
구간 전체에 값을 더하는 요청은 구간을 덮는 노드에 메모를 남겨 두었다가, 자식으로 내려갈 때만 넘겨 O(log n)에 처리합니다.
합처럼 빼기로 되돌릴 수 있는 연산이라면 n + 1 칸 배열과 짧은 반복문만으로 같은 복잡도를 내는 펜윅 트리(BIT)를 쓸 수 있습니다.
크기 2n 배열의 뒤쪽 절반에 원소를 두고, 앞쪽에는 두 자식의 합을 저장하는 반복문 구간 트리입니다. update는 리프에서 루트까지 올라가며 합을 다시 계산하고, query는 반열린 구간 [left, right)의 양 끝에서 올라가며 경계에 걸친 노드만 더합니다. 실행하면 26, 17, 28이 차례로 출력됩니다.
segment_tree.py
class SegmentTree:
"""Iterative segment tree: point update and range sum in O(log n)."""
def __init__(self, values):
self.n = len(values)
self.tree = [0] * self.n + list(values)
for i in range(self.n - 1, 0, -1):
self.tree[i] = self.tree[2 * i] + self.tree[2 * i + 1]
def update(self, index, value):
i = index + self.n
self.tree[i] = value
while i > 1:
i //= 2
self.tree[i] = self.tree[2 * i] + self.tree[2 * i + 1]
def query(self, left, right):
"""Sum of values[left:right] (half-open range)."""
total = 0
lo, hi = left + self.n, right + self.n
while lo < hi:
if lo & 1:
total += self.tree[lo]
lo += 1
if hi & 1:
hi -= 1
total += self.tree[hi]
lo //= 2
hi //= 2
return total
if __name__ == "__main__":
tree = SegmentTree([5, 3, 7, 9, 6, 4, 1, 2])
print(tree.query(2, 6)) # 7 + 9 + 6 + 4 = 26
tree.update(3, 0)
print(tree.query(2, 6)) # 7 + 0 + 6 + 4 = 17
print(tree.query(0, 8)) # 28
python segment_tree.py구간 트리 에 관해 묻고, 경험을 나누고, 의견을 주고받는 곳입니다.
아직 토론이 없습니다. 첫 이야기를 시작해 보세요.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.