Segment Tree
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ๋ฐฐ์ด ์์์ ๋น ๋ฅด๊ฒ โ๊ตฌ๊ฐ ์ฐ์ฐโ ๋๋ โ๊ฐฑ์ ์ฐ์ฐโ์ ์ํํด์ผ ํ ๋ ์ ์ฉํ๋ค. ๋ณธ ํฌ์คํธ๋ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์ ๋ํ ์์ธํ ์ด๋ก ๋ณด๋ค๋ ์ฝ๋ ๋ ๋ฒจ์ ํจ๊ป ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ฅผ ์ดํดํ๊ณ ๊ธฐ๋กํ๊ณ ์ ์์ฑํ๋ค. ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์ ๋ํ ์ด๋ก ์ ์ ํ๋ธ ์์ โ[์๊ณ ๋ฆฌ์ฆ ๊ฐ์] ์ธ๊ทธ๋จผํธ ํธ๋ฆฌโ๋ฅผ ์ฐธ๊ณ ํ์.
- Segment Tree๋?
- Segment Tree์ ๊ตฌ์กฐ
- ์ฝ๋๋ ์ด๋ป๊ฒ ์ง์ผํ ์ง
- ์ด๋ป๊ฒ ํ์ฉํ ์ง
- ํจํด์ด ์๋ค!
- ์ฌ์ค ๋๋ ์๊ฑด ์์ง ์ผ๋ง ์ ๋ ๋ ์์ด๋ค!
Segment Tree๋?
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ(Segment Tree)๋ ๋ฐฐ์ด์์ ์ ์ฐ์ฐ ๋๋ ๊ตฌ๊ฐ ์ฐ์ฐ์ ์ํํ ๋ ์ธ ์ ์๋ โ์๋ฃ๊ตฌ์กฐโ๋ค. ์ฒ์์๋ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์ ๋ํ ์ ์๋ณด๋ค๋ ๊ตฌ์ฒด์ ์ธ ์ํฉ์ ๋ฐํ์ผ๋ก ์ดํดํด์ผ ํ๋ค.
๋ฐฐ์ด arr
์ ๋ํด ์๋์ 2๊ฐ์ง ์ฐ์ฐ์ ์ํํด๋ณด์.
- ๊ตฌ๊ฐ
left
,right
(left < right
)์ ๋ํด ๊ตฌ๊ฐํฉarr[left] + ... + arr[right]
์ถ๋ ฅ - ๋ฐฐ์ด์ i๋ฒ์งธ ์๋ฅผ
v
๋ก ๋ฐ๊พธ๊ธฐ:arr[i] = v
1๋ฒ, 2๋ฒ ์ฐ์ฐ์ ๊ฐ๊ฐ ๊ตฌ๊ฐํฉ, ์ ๊ฐฑ์ ์ฐ์ฐ์ด๋ผ๊ณ ์ด๋ฆ ๋ถ์ด๊ฒ ๋ค.
์ด ๋ฌธ์ ๋ฅผ Brute Force๋ก ์ ๊ทผํด๋ณด์. ๊ตฌ๊ฐํฉ์ ํ๋ฒ ์ฐ์ฐ์ $O(N)$, ์ ๊ฐฑ์ ์ $O(1)$์ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค. ์ฐ์ฐ์ $M$๋ฒ ์ํํ๋ค๋ฉด, ์ต๋ $O(NM)$์ ๋น์ฉ์ด ๋ ๋ค.
๊ทธ๋ฌ๋ $O(NM)$ ์๊ฐ ๋ณต์ก๋๋ $N$ ๋๋ $M$์ด ๋งค์ฐ ํฐ ๊ฒฝ์ฐ์๋ ์๊ฐ์ด ๋๋ฌด ์ค๋ ๊ฑธ๋ฆฐ๋ค. ๊ทธ๋ฐ๋ฐ! ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ฅผ ์ด์ฉํ๋ฉด ๊ตฌ๊ฐํฉ์ $O(\log N)$, ์ ๊ฐฑ์ ์ $O(\log N)$์ ์ํํ ์ ์์ด $O(M \log N)$์ ๋น์ฉ์ผ๋ก ๋ชจ๋ ์ฐ์ฐ์ ์ฒ๋ฆฌํ ์ ์๋ค!!
Segment Tree์ ๊ตฌ์กฐ
Segment Tree๋ ํธ๋ฆฌ ํํ์ ์๋ฃ๊ตฌ์กฐ์ด๋ค. ๊ตฌ์ฒด์ ์ผ๋ก Full Binary Tree์ด๋ค. ๋ชจ๋ ๋
ธ๋๊ฐ 0๊ฐ ํน์ 2๊ฐ์ ์์ ๋
ธ๋๋ฅผ ๊ฐ๋ ํธ๋ฆฌ๋ฅผ ๋งํ๋ค. ๊ทธ๋์ ๋ถ๋ชจ-์์ ๋
ธ๋ ์ฌ์ด์ node <-> node*2, node*2+1
์ ๊ด๊ณ๊ฐ ์ฑ๋ฆฝํ๋ค.
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์์ ๊ฐ ๋ ธ๋๋ ์๋์ ๊ฐ์ ์๋ฏธ๋ฅผ ๊ฐ๋๋ค.
- ๋ฆฌํ ๋
ธ๋
- ๋ฐฐ์ด์์ ๊ทธ ์ ์์ฒด๋ค.
arr[i]
๋ผ๋ ๋ง
- ๊ตฌ๊ฐ ๋
ธ๋
- ์ผ์ชฝ ์์๊ณผ ์ค๋ฅธ์ชฝ ์์์ ํฉ์ ์ ์ฅ
tree[i] = tree[2*i] + tree[2*i+1]
๋ฐฐ์ด ๊ฐฏ์ $N$์ด 10์ธ ๊ฒฝ์ฐ ํธ๋ฆฌ๋ ์๋์ ๊ฐ๋ค.
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์์ ๋
ธ๋์ ํ์๋ ์ซ์ ๋๋ ๋ฒ์๋ ํด๋น ๋
ธ๋๊ฐ ์ ์ฅํ ๊ตฌ๊ฐํฉ์ ๋ฒ์์ด๋ค. ์๋ฅผ ๋ค์ด, ๋
ธ๋์ ํ์๋ ๋ฒ์๊ฐ 5~7
์ด๋ผ๋ฉด, arr[5] + arr[6] + arr[7]
์ ์๋ฏธ์ด๋ค. ๊ทธ๋ผ ๋น์ฐํ๊ฒ๋ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์ ๋ฃจํธ๋
ธ๋๋ ์ ์ฒด ๋ฐฐ์ด์ ํฉ์ ์ ์ฅํ๋ค.
Segment Tree ์ด๊ธฐํ
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ Full Binary Tree์ฌ์ผ ํ๋ค. ๋ฆฌํ ๋ ธ๋๊ฐ $N$๊ฐ์ธ Full Binary Tree์ ๋์ด $H$๋ $H = \lceil \log N \rceil$์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด $(2 \times H - 1)$๊ฐ ๋งํผ์ ๋ ธ๋๊ฐ ํ์ํ๋ค. ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ด๊ธฐํ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ์๋์ ๊ฐ๋ค.
int h = (int) ceil(log2(n));
int tree_size = (1 << (h+1));
vector<llong> tree(tree_size);
์ด์ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ tree
์ ๋
ธ๋์ ๊ฐ์ ํ ๋นํด์ผ ํ๋ค. ๋ฆฌํ ๋
ธ๋์ธ์ง ์ค๊ฐ ๋
ธ๋์ธ์ง์ ๋ฐ๋ผ ๊ฐ์ ํ ๋น ํด์ฃผ๋ฉด ๋๋ค.
// main
vector<llong> tree;
tree.assign(tree_size, 0);
init(arr, tree, 1, 0, N-1);
llong init(vector<llong> &arr, vector<llong> &tree, int node, int start, int end) {
if (start == end) // ๋ฆฌํ ๋
ธ๋์.
return tree[node] = arr[start];
int mid = (start + end) / 2;
llong left = init(arr, tree, node * 2, start, mid);
llong right = init(arr, tree, node * 2 + 1, mid + 1, end);
tree[node] = left + right;
return tree[node];
}
์ด๊ธฐํ ํจ์ init()
์์ node
๋ ๊ฐ์ ํ ๋นํ๊ณ ์ ํ๋ ๋
ธ๋๋ฅผ ์๋ฏธํ๋ค. start
์ end
๋ ํด๋น node
๊ฐ ์ปค๋ฒํ๋ ๋ฒ์๋ฅผ ์๋ฏธํ๋ค.
๊ตฌ๊ฐํฉ
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์ ์ฑ์ง์ ๋ฐ๋ผ ๊ตฌ๊ฐ ๋
ธ๋์ ๊ฐ์ ์กฐํฉํด ๊ตฌ๊ฐํฉ์ ๊ตฌํ ์ ์๋ค. ์ด๋ฅผ ์ํด sum()
ํจ์๋ฅผ ์์ฑํ์.
๋จผ์ ๋ณ์ ์ด๋ฆ์ ๋ถ๋ช
ํ ํ์. ์ฌ๊ธฐ์ start ~ end
๋ ํธ๋ฆฌ ๋
ธ๋ node
๊ฐ ์ปค๋ฒํ๋ ๋ฒ์์ด๋ค. ์ฐ๋ฆฌ๊ฐ ๊ตฌ๊ฐํฉ์ ๊ตฌํ๊ณ ์ ํ๋ ๋ฒ์๋ left ~ right
์ด๋ค.
llong sum(vector<llong> &tree, int node, int start, int end, int left, int right) {
// queryํ๋ ๋ฒ์ (left, right)์ ๋
ธ๋ ๋ฒ์ (start, end)๊ฐ ๊ฒน์น์ง ์์.
if (left > end || right < start)
return 0;
// ๊ตฌํด์ผํ๋ ํฉ์ ๋ฒ์๋ [left, right]์ธ๋ฐ,
// [start, end]๋ ๊ทธ ๋ฒ์์ ๋ชจ๋ ํฌํจ๋๋ค.
// ๊ทธ๋ฌ๋ฉด node์ ์์๋ ๋ชจ๋ ํฌํจ๋๊ธฐ ๋๋ฌธ์
// ๋ ์ด์ ํธ์ถ์ ํ๋ ๊ฒ์ ๋นํจ์จ์ ์ด๋ค.
if (left <= start && end <= right)
return tree[node];
int mid = (start + end) / 2;
llong leftSum = sum(tree, node * 2, start, mid, left, right);
llong rightSum = sum(tree, node * 2 + 1, mid+1, end, left, right);
return leftSum + rightSum;
}
์ ๊ฐฑ์
์ ๊ฐฑ์ ์ ๋ฐฐ์ด arr[i]
๊ฐ ๊ฐฑ์ ๋๋ ๊ทธ ๊ฐ์ด ์๋๋ผ ์ฐจ์ด๊ฐ์ธ diff
๋ฅผ ์ด์ฉํด ๋
ธ๋์ ๊ฐ์ ๊ฐฑ์ ํ๋ค. ์ด๋, ํด๋น ๋ฆฌํ ๋
ธ๋๊ฐ ํฌํจ๋ ๋ชจ๋ ๊ตฌ๊ฐ ๋
ธ๋๋ค์ ๊ฐฑ์ ํด์ค์ผ ํ๋ค.
// main
llong diff = new_value - arr[idx];
arr[idx] = new_value;
update(tree, 1, 0, N-1, idx, diff);
void update(vector<llong> &tree, int node, int start, int end, int index, llong diff) {
// index๊ฐ ๋
ธ๋ ๋ฒ์ (start, end)์ ๊ฒน์น์ง ์์.
if (index < start || end < index)
return;
tree[node] += diff;
// ๋ฆฌํ ๋
ธ๋๋ start == end์.
// ๋ฆฌํ๊ฐ ์๋๋ผ๋ฉด, ์๋์ ์์๋
ธ๋๋ ์
๋ฐ์ดํธ ํด์ค์ผ ํจ.
if (start != end) {
int mid = (start + end) / 2;
update(tree, node * 2, start, mid, index, diff);
update(tree, node * 2 + 1, mid+1, end, index, diff);
}
}
๋งบ์๋ง
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ๊ทธ ์กด์ฌ๊ฐ ๋๋ฌธ์ ์ผ๋จ ์์ํ๋๊ฒ ์ด๋ ต์ง ๋ง ์ก๊ณ ๊ณต๋ถํ๋ฉด ๊ธ๋ฐฉ ์ต์ํด์ง๋ค. โ๋ฐฐ์ด ์์์์ ๊ตฌ๊ฐ ์ฐ์ฐ, ์ ์ฐ์ฐโ์ด๋ผ๋ ํน์ง ๋๋ฌธ์ ์กฐ๊ธ์ ๊ฐ๋ง ์์ผ๋ฉด ์ด๋ค ๋ฌธ์ ๋ฅผ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ก ํ์ด์ผ ํ๋์ง ๋์น ์ฑ ์ ์๋ค!
์๊ฐ์ด ๋ ๋ Multiset์ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ ๊ตฌํ๊ณผ, Lazy Segment Tree์ ๋ํด ๊ณต๋ถํ๊ณ ํฌ์คํธ๋ฅผ ์์ฑํด๋ณด๊ฒ ๋ค ๐