์ธ๊ทธ๋จผํธ ํธ๋ฆฌ(Segment Tree)๋ ์ฃผ๋ก ๊ตฌ๊ฐ ์ฟผ๋ฆฌ(range query)์ ๊ตฌ๊ฐ ์ ๋ฐ์ดํธ(range update)๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ์๋ฃ ๊ตฌ์กฐ์ ๋๋ค. ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ์ด์ง ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋ฉฐ, ๊ฐ ๋ ธ๋๋ ํน์ ๊ตฌ๊ฐ์ ๊ฐ์ ์ ์ฅํด ๊ตฌ๊ฐํฉ, ์ต์๊ฐ, ์ต๋๊ฐ ๋ฑ์ ๋น ๋ฅด๊ฒ ๊ณ์ฐํ ์ ์์ด์. โก
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ๋ฐฐ์ด์ ๊ฐ์ ํธ๋ฆฌ ํํ๋ก ํํํ ์๋ฃ ๊ตฌ์กฐ๋ก, ๊ฐ ๋ ธ๋๋ ๋ฐฐ์ด์ ๋ถ๋ถ ๊ตฌ๊ฐ์ ๋ํ๋ ๋๋ค.
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ๋ฐฐ์ด์ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋๋ฉฐ, ํธ๋ฆฌ๋ก ๋ณํํ๋ ๋ฐ (O(n)) ์๊ฐ์ด ์์๋ฉ๋๋ค.
def build_segment_tree(arr, tree, node, start, end):
if start == end:
# ๋ฆฌํ ๋
ธ๋์ ๋ฐฐ์ด์ ๊ฐ์ ์ ์ฅ
tree[node] = arr[start]
else:
mid = (start + end) // 2
# ์ผ์ชฝ ์์ ๋
ธ๋
build_segment_tree(arr, tree, 2 * node, start, mid)
# ์ค๋ฅธ์ชฝ ์์ ๋
ธ๋
build_segment_tree(arr, tree, 2 * node + 1, mid + 1, end)
# ๋ถ๋ชจ ๋
ธ๋๋ ์์ ๋
ธ๋๋ค์ ๊ฐ์ ํฉ์นจ
tree[node] = tree[2 * node] + tree[2 * node + 1]
์ํ๋ ๊ตฌ๊ฐ [L, R]์ ๊ฐ์ ์ฐพ๊ธฐ ์ํด ํธ๋ฆฌ์์ ๊ตฌ๊ฐ ์ฟผ๋ฆฌ๋ฅผ ์ํํฉ๋๋ค.
def range_query(tree, node, start, end, L, R):
if R < start or end < L:
# ๊ตฌ๊ฐ์ด ์์ ํ ๊ฒน์น์ง ์์ผ๋ฉด ๋ฌด์
return 0
if L <= start and end <= R:
# ๊ตฌ๊ฐ์ด ์์ ํ ํฌํจ๋๋ฉด ํ์ฌ ๋
ธ๋ ๊ฐ์ ๋ฐํ
return tree[node]
# ๋ถ๋ถ์ ์ผ๋ก ๊ฒน์น๋ ๊ฒฝ์ฐ ์์ ๋
ธ๋๋ก ์ฟผ๋ฆฌ ๋ถํ
mid = (start + end) // 2
left_sum = range_query(tree, 2 * node, start, mid, L, R)
right_sum = range_query(tree, 2 * node + 1, mid + 1, end, L, R)
return left_sum + right_sum
๋ฐฐ์ด์ ํน์ ๊ฐ์ ๋ณ๊ฒฝํ ๋, ํด๋น ๊ฐ์ด ํฌํจ๋ ๊ตฌ๊ฐ์ ๋ ธ๋๋ค๋ ์ ๋ฐ์ดํธํฉ๋๋ค.
def update(tree, node, start, end, idx, val):
if start == end:
# ๋ฆฌํ ๋
ธ๋ ์
๋ฐ์ดํธ
tree[node] = val
else:
mid = (start + end) // 2
if start <= idx <= mid:
# ์ผ์ชฝ ์์ ๋
ธ๋ ์
๋ฐ์ดํธ
update(tree, 2 * node, start, mid, idx, val)
else:
# ์ค๋ฅธ์ชฝ ์์ ๋
ธ๋ ์
๋ฐ์ดํธ
update(tree, 2 * node + 1, mid + 1, end, idx, val)
# ๋ถ๋ชจ ๋
ธ๋๋ ์์ ๋
ธ๋๋ค์ ๊ฐ์ผ๋ก ๋ค์ ๊ณ์ฐ
tree[node] = tree[2 * node] + tree[2 * node + 1]
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ๋ค์ํ ๋ฌธ์ ์ ํ์ฉ๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด:
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ์ด๋ ๊ฒ ์๊ฐ ๋ณต์ก๋ (O(log n))๋ก ํจ์จ์ ์ผ๋ก ๋์ํด, ํฐ ๋ฐ์ดํฐ์ ์์๋ ์ฑ๋ฅ์ ๋ณด์ฅํ ์ ์์ต๋๋ค. ๐ก