๋ถ€๋ถ„ํ•ฉ
ย - Last update: 2023-05-22

๋ถ€๋ถ„ํ•ฉ ๊ด€๋ จ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ •๋ฆฌ

๋ถ€๋ถ„ํ•ฉ๊ณผ ์ฟผ๋ฆฌ

Query๋ž€, ์ด๋ฅผํ…Œ๋ฉด ํŠน์ • Range์˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ์ด๋Ÿฌํ•œ Query์— ๋”ฐ๋ผ ๋ถ€๋ถ„ํ•ฉ์„ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์„ ๋‹ค๋ฅด๊ฒŒ ํ•ด์•ผํ•œ๋‹ค.

๋ฐฐ์—ด์ด ๋ณ€ํ•˜์ง€ ์•Š๊ณ  Query๊ฐ€ ๊ณ„์†๋  ๊ฒฝ์šฐ

์ด ๊ฒฝ์šฐ์—๋Š” ๊ฐ€์žฅ ๋‹จ์ˆœํ•˜๋ฉด์„œ๋„ ์‹ฌํ”Œํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

int pSum[MAX];
void init(int arr[]) {
pSum[0] = arr[0];
for(int i = 1; i < MAX; ++i) {
pSum[i] = pSum[i-1] + arr[i];
}
}
int getRangeSum(int l, int r) {
if (l == 0) return pSum[r];
return pSum[r] - pSum[l - 1];
}

์ด ๊ฒฝ์šฐ ์ฒ˜์Œ init์ด ๋œ ์ดํ›„์—๋Š” ๋ฌด๋ ค O(1)๋กœ ๋ถ€๋ถ„ํ•ฉ์„ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์ด๋ ‡๊ฒŒ๋งŒ ๋˜๋ฉด ๋„ˆ๋ฌด ์‰ฌ์šฐ๋‹ˆ, ๋ณดํ†ต ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์‹œํ—˜์ด๋‚˜ ์ด๋Ÿฐ ๊ณณ์—์„œ๋Š” arr์˜ ๊ฐ’์„ ์ง€์†์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ํ˜•ํƒœ์˜ ๋ฌธ์ œ๊ฐ€ ์ถœ์ œ๋˜๊ณค ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์›๋ณธ ๋ฐฐ์—ด์˜ ๊ฐ’์ด ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ์—๋Š” ๊ธฐ์กด์— ๊ตฌํ•ด๋†“์€ pSum์˜ ๊ฐ’์ด ๋ฌด์šฉ์ง€๋ฌผ์ด๊ณ , ๊ฐ’์— ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค O(n)์˜ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค.

Fenwick Tree

๋ถ€๋ถ„ํ•ฉ์„ ๊ตฌํ•  ๋•Œ ์žˆ์–ด์„œ ๊ฐ€์žฅ ์•„๋ฆ„๋‹ค์šด ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ๋‚˜๋Š” ์ƒ๊ฐํ•œ๋‹ค. ์ด ํŠธ๋ฆฌ๋Š” Binary-Indexed Tree ๋ผ๊ณ ๋„ ๋ถˆ๋ฆฌ๋ฉฐ, ์ถ”ํ›„ ์†Œ๊ฐœํ•  Segment Tree์™€ ๋‹ค๋ฅด๊ฒŒ, ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ N ๋งŒํผ๋งŒ ์‚ฌ์šฉํ•˜๊ณ ๋„ ๋ถ€๋ถ„ํ•ฉ์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์–ด๋–ป๊ฒŒ N ๋งŒํผ์œผ๋กœ ์ €์žฅํ•˜๋Š”๊ฐ€? ์ด์ง„์ˆ˜์˜ ์›๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ํŠน์ • Index์˜ ๊ฐ’์„ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด, ์•„๋ž˜์ฒ˜๋Ÿผ ํ•œ๋‹ค.

  • 11 (1011) -> 12 (1100) -> 16 (10000) -> 32 (100000) -> ...
  • 7 (0111) -> 8 (1000) -> 16 (10000) -> 32 (100000) -> ...

์ด๋ ‡๊ฒŒ ํ•  ๊ฒฝ์šฐ, ์ „์ฒด ์—…๋ฐ์ดํŠธ ๋  Index์˜ ๊ฐœ์ˆ˜๋Š” log n๊ฐœ๊ฐ€ ๋˜๋ฏ€๋กœ, ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ O(n)์—์„œ ๋งŽ์ด ์ค„์–ด๋“ค๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ํŠน์ • Index ๊นŒ์ง€์˜ ํ•ฉ์„ ๊ตฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์•„๋ž˜ ์ˆœ์„œ๋กœ ํ•ฉํ•œ๋‹ค.

  • 11 (1011) -> 10 (1010) -> 8 (1000)
  • 7 (0111) -> 6 (0110) -> 4 (0100)

์ด ๊ณผ์ •๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ด์ง„์ˆ˜ ๋‹จ์œ„๋กœ ์—…๋ฐ์ดํŠธ ๋˜๋ฏ€๋กœ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” O(log n) ์ด๋‹ค.

์ฝ”๋“œ๋กœ ์œ„ ๋‘ ๊ณผ์ •์„ ๊ตฌํ˜„ํ•˜๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ๋œ๋‹ค.

int f[MAX];
void update(int idx, int v) {
for(; idx < MAX; idx += idx & -idx) f[idx] += v;
}
int get(int idx) {
int r = 0;
for(; idx > 0; idx -= idx & -idx) r += f[idx];
return r;
}

์ฝ”๋“œ์—์„œ ๋“œ๋Ÿฌ๋‚œ ๊ฒƒ์ฒ˜๋Ÿผ, ๋งŒ์•ฝ n๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด O(n log n)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ ์†Œ์š”๋œ๋‹ค.

Segment Tree

Segment Tree๋Š” ์ผ๋ฐ˜์ ์ธ Query๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ตฌ์กฐ์ด๋‹ค.

์ž‘์„ฑ ์ค‘

๐Ÿท๏ธ ์ฃผ์ œ ๋ชฉ๋ก: