7 minute read


์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋Š” ๋ฐฐ์—ด ์œ„์—์„œ ๋น ๋ฅด๊ฒŒ โ€œ๊ตฌ๊ฐ„ ์—ฐ์‚ฐโ€ ๋˜๋Š” โ€œ๊ฐฑ์‹  ์—ฐ์‚ฐโ€์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค. ๋ณธ ํฌ์ŠคํŠธ๋Š” ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ด๋ก  ๋ณด๋‹ค๋Š” ์ฝ”๋“œ ๋ ˆ๋ฒจ์™€ ํ•จ๊ป˜ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ  ๊ธฐ๋กํ•˜๊ณ ์ž ์ž‘์„ฑํ–ˆ๋‹ค. ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ์— ๋Œ€ํ•œ ์ด๋ก ์€ ์œ ํŠœ๋ธŒ ์˜์ƒ โ€œ[์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ฐ•์˜] ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌโ€œ๋ฅผ ์ฐธ๊ณ ํ•˜์ž.

  • Segment Tree๋ž€?
  • Segment Tree์˜ ๊ตฌ์กฐ
  • ์ฝ”๋“œ๋Š” ์–ด๋–ป๊ฒŒ ์งœ์•ผํ• ์ง€
  • ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ• ์ง€
    • ํŒจํ„ด์ด ์žˆ๋‹ค!
  • ์‚ฌ์‹ค ๋‚˜๋„ ์š”๊ฑด ์•ˆ์ง€ ์–ผ๋งˆ ์•ˆ ๋œ ๋…€์„์ด๋‹ค!

Segment Tree๋ž€?

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ(Segment Tree)๋Š” ๋ฐฐ์—ด์—์„œ ์  ์—ฐ์‚ฐ ๋˜๋Š” ๊ตฌ๊ฐ„ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ์“ธ ์ˆ˜ ์žˆ๋Š” โ€œ์ž๋ฃŒ๊ตฌ์กฐโ€๋‹ค. ์ฒ˜์Œ์—๋Š” ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ์— ๋Œ€ํ•œ ์ •์˜๋ณด๋‹ค๋Š” ๊ตฌ์ฒด์ ์ธ ์ƒํ™ฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค.

๋ฐฐ์—ด arr์— ๋Œ€ํ•ด ์•„๋ž˜์˜ 2๊ฐ€์ง€ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ด๋ณด์ž.

  1. ๊ตฌ๊ฐ„ left, right (left < right)์— ๋Œ€ํ•ด ๊ตฌ๊ฐ„ํ•ฉ arr[left] + ... + arr[right] ์ถœ๋ ฅ
  2. ๋ฐฐ์—ด์˜ 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์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜๊ณ  ํฌ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ๋‹ค ๐Ÿ˜‰

๊ด€๋ จ ๋ฌธ์ œ

References

Categories:

Updated: