[python] ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ ๊ตฌํ˜„ํ•˜๊ธฐ (segment tree) - ์ตœ์†Œ๊ฐ’ ๊ตฌํ•˜๊ธฐ

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ

https://www.acmicpc.net/blog/view/9

๋ฐฑ์ค€๋‹˜ ๊ธ€

๋ฐฐ์—ด ํฌ๊ธฐ ๊ฒฐ์ •

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ C++์˜ ๊ฒฝ์šฐ, vector ์ž๋ฃŒํ˜•์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ python์œผ๋กœ ๊ตฌํ˜„ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋˜์–ด์•ผ ํ• ์ง€ ๊ฐ€๋Š ํ•˜๊ธฐ ์œ„ํ•ด ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•ด๋ณด์ž.

2์˜ ์ œ๊ณฑ ์ˆ˜๊ฐ€ ๋ฆฌํ”„ ๋…ธ๋“œ์˜ ์ˆ˜(n)๋กœ ์ฃผ์–ด์ง„๋‹ค๋ฉด ( ๋ถ„์„ํ•ด์•ผํ•  data ๊ฐฏ์ˆ˜๊ฐ€ 2์˜ ์ œ๊ณฑ ์ˆ˜๋ผ๋ฉด ) ๊ฐ ๋‹จ๊ณ„๋งˆ๋‹ค 1/2์”ฉ ์ค„์–ด๋‚˜๊ฐ€๋ฏ€๋กœ log(n)์ด ํ•„์š”ํ•œ ์ด ๋‹จ๊ณ„(ํ™”์‚ดํ‘œ)๊ฐ€ ๋˜๊ณ  ์ „์ฒด ์ธต์˜ ๊ฐฏ์ˆ˜, ์ฆ‰ ๋†’์ด(h)๋Š” log(n)+1์ด ๋œ๋‹ค.

์ตœ์ƒ์œ„ ๋…ธ๋“œ๋ถ€ํ„ฐ 2^(0)๊ฐœ์˜ ๋…ธ๋“œ๋กœ ์‹œ์ž‘ํ•˜์—ฌ ์ธต์ด ์ฆ๊ฐ€ํ•  ์ˆ˜๋ก 2์˜ ์ง€์ˆ˜ ๋˜ํ•œ ์ฆ๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฝ‰์ฐฌ ์ด์ค‘ ํŠธ๋ฆฌ(full binary tree)์˜ ์ด ๋…ธ๋“œ ์ˆ˜๋Š” 2^(0)+2^(1)+...+2^(h-1) (h๋Š” ๋†’์ด) ๊ฐ€ ๋˜์–ด 2^(h)-1 ๊ฐœ ์ด๋‹ค.

h = log(n)+1 ์ด๋ฏ€๋กœ ํ•„์š”ํ•œ ๋…ธ๋“œ์˜ ์ˆ˜๋Š” 2^(log(n)+1)-1 ๊ฐœ์ด๋‹ค.

2์˜ ์ œ๊ณฑ ์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ๋„ ๋˜‘๊ฐ™์ด ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค๋งŒ ์ •์ˆ˜๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š์œผ๋ฏ€๋กœ ์˜ฌ๋ฆผํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ์œ„์˜ ๊ทธ๋ฆผ์— ํ‘œ์‹œ๋œ ํšŒ์ƒ‰ ๋™๊ทธ๋ผ๋ฏธ๋“ค์€ ์กด์žฌํ•˜์ง€๋งŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฐฐ์—ด์˜ ์š”์†Œ๋“ค์ด๋‹ค.

๋”ฐ๋ผ์„œ ์ฒ˜์Œ์— tree ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋Š” 2^(log(n)+1)-1์ด๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค.

tree_list = [0]*(pow(2,math.ceil(math.log(len(a),2))+1))-1 #a๋Š” ๋ฐฐ์—ด
# math.log(๊ฐฏ์ˆ˜,2) => log(๊ฐฏ์ˆ˜)
# math.ceil => ์˜ฌ๋ฆผ
# pow(2,์ˆซ์ž) => 2^(์ˆซ์ž)

์ผ๋‹จ ํ•„์ž๋Š” ์ตœ์†Œ์˜ ๊ฐ’์„ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ์œผ๋ฏ€๋กœ ๋ชจ๋“  ๊ฐ’์„ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

init

์ผ๋‹จ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ฃผ์–ด์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•ด์„œ ์ฑ„์›Œ์•ผํ•œ๋‹ค. ๋”ฐ๋ผ์„œ init ํ•จ์ˆ˜๋ฅผ ๋”ฐ๋กœ ๊ตฌํ˜„ํ•˜์—ฌ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ฑ„์šฐ๊ธฐ๋กœ ํ•˜์ž. init ํ•จ์ˆ˜๋Š” 2๊ฐœ์”ฉ ๊ฒ€์‚ฌํ•˜์—ฌ ๋” ์ž‘์€ ์ˆ˜๋ฅผ ์œ„๋กœ ์˜ฌ๋ฆฌ๋Š” ํŠธ๋ฆฌ์˜ ํ˜•ํƒœ๋ฅผ ๋„์–ด์•ผํ•˜๋ฏ€๋กœ ์žฌ๊ท€ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„ํ•  ๊ฒƒ์ด๋‹ค. ์ด ๋•Œ, ๊ธฐ์ €์‚ฌ๋ก€๋Š”(ํƒˆ์ถœ ์กฐ๊ฑด์€) ๋ฆฌํ”„๋…ธ๋“œ์ด๋‹ค.

def init(a, tree, node, start, end):
    if start == end:
        tree[node-1] = start
    else:
        init(a,tree,node*2,start,(start+end)//2)
        init(a,tree,node*2+1,(start+end)//2+1,end)
        if a[tree[node*2-1]]<a[tree[node*2]]:
            tree[node-1] = tree[node*2-1]
        else:
            tree[node-1] = tree[node*2]

ํ•˜๋‚˜์˜ ์˜ˆ์ œ๋ฅผ ๊ฐ€์ง€๊ณ  ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ๊ฐ’๋“ค์„ ์ข‡๋‹ค๋ณด๋ฉด ์–ด๋–ป๊ฒŒ ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ๊ตฌ์„ฑ๋˜์—ˆ๋Š”์ง€ ์•Œ๊ฒƒ์ด๋‹ค. ํŠธ๋ฆฌ์—๋Š” ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์˜ ๊ฐ’์ด ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ธ๋ฑ์Šค๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. ํ•„์ž๋Š” ์ผ์ „์— ์–ธ๊ธ‰ํ•œ ๋ฐ”์™€ ๊ฐ™์ด ๊ฐ€์žฅ ์ž‘์€ ์ตœ์†Ÿ๊ฐ’์„ ์ฐพ๊ธฐ ์œ„ํ•ด ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

query

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ตœ์†Ÿ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ณผ์ •์—์„œ ๋ฐฐ์—ด ์ „์ฒด๋ฅผ ๋”ฐ์ง€์ž๋ฉด ๋ฐฐ์—ด์˜ 0๋ฒˆ์งธ index ๊ฐ’์— ํ•ด๋‹นํ•˜๋Š” ๋ถ€๋ถ„๋งŒ ์‚ดํŽด๋ณด๋ฉด ๋œ๋‹ค. ์ตœ์ƒ์œ„ ๋…ธ๋“œ๊ฐ€ ๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋กœ ์ €์žฅ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ ๋ฒˆ ๋‹ค๋ฅธ ๋ฒ”์œ„๋กœ ์ ‘๊ทผํ•˜๋ฉด์„œ ๊ทธ ๋ฒ”์œ„์—์„œ์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ฐพ์œผ๋ ค๊ณ  ํ•  ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ๋งค๋ฒˆ ๋ฒ”์œ„์— ํ•ด๋‹นํ•˜๋Š” ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์„œ ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๋„ ํ•œ ๋ฐฉ๋ฒ•์ด๊ฒ ์ง€๋งŒ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ query๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ํ•ด๋‹น ๋ฒ”์œ„์—์„œ์˜ ์ตœ์†Ÿ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋„๋ก ํ•œ๋‹ค.

def query(a,tree,node,start,end,i,j):
    if i>end or j<start: # ์ฃผ์–ด์ง„ ๋ฒ”์œ„๊ฐ€ ์ „์ฒด ๋ฒ”์œ„์— ์™„์ „ํžˆ ์†ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด
        return -1 
    if i<=start and end<=j: # ์ฃผ์–ด์ง„ ๋ฒ”์œ„๊ฐ€ ์ „์ฒด ๋ฒ”์œ„๋ฅผ ์™„์ „ํžˆ ํฌํ•จํ•œ๋‹ค๋ฉด
        return tree[node-1] # ํ•ด๋‹น ๋ฒ”์œ„์˜ ์ตœ์†Œ๊ฐ’ index๋ฅผ return ํ•จ

    # ์ฃผ์–ด์ง„ ๋ฒ”์œ„๊ฐ€ ์ „์ฒด ๋ฒ”์œ„์— ์†ํ•ด์žˆ๋‹ค๋ฉด
    # ex_) 0~4 index์˜ ๊ฐ’์ด ์ฃผ์–ด์กŒ์„ ๋•Œ, 1~3 index์— ๋Œ€ํ•œ ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•˜๊ณ  ์‹ถ์Œ
    m1 = query(a,tree,2*node,start,(start+end)//2,i,j) # ์ „์ฒด ๋ฒ”์œ„๋ฅผ ๋ฐ˜์œผ๋กœ ์ž๋ฅธ ๋ฒ”์œ„๋ฅผ ๋„˜๊ธฐ๊ณ  ์™ผ์ชฝ ๋…ธ๋“œ ๊ฐ’์„ ๋„˜๊น€
    m2 = query(a,tree,2*node+1,(start+end)//2+1,end,i,j) # ์ „์ฒด ๋ฒ”์œ„๋ฅผ ๋ฐ˜์œผ๋กœ ์ž๋ฅธ ๋ฒ”์œ„๋ฅผ ๋„˜๊ธฐ๊ณ  ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ ๊ฐ’์„ ๋„˜๊น€
    if m1==-1:
        return m2
    elif m2==-1:
        return m1
    else:
        if a[m1]<=a[m2]:
            return m1
        else:
            return m2

ํ•ด๋‹น ๊ทธ๋ฆผ๊ณผ ์ฝ”๋“œ๋ฅผ ๊ฐ™์ด ์‚ดํŽด๋ณด๋ฉด ํ•ด๋‹น ๊ทธ๋ฆผ์—์„œ 1-4 ์‚ฌ์ด์˜ ์ตœ์†Œ๊ฐ’์„ ์ฐพ๊ณ ์ž ํ•  ๋•Œ ํ•„์š”ํ•œ ๋…ธ๋“œ๋Š”

์œ„์˜ 3๊ฐ€์ง€ ๋…ธ๋“œ์ด๋‹ค. query ํ•จ์ˆ˜์— i,j ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด 1,4๋ฅผ ๋„˜๊ธฐ๋ฉด ์ฒ˜์Œ์—๋Š” if๋ฌธ 2๊ฐœ๋ฅผ ํ†ต๊ณผํ•˜๊ณ  m1,m2๋ฅผ ๊ณ„์‚ฐํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ๋•Œ m1์€ 0-2, m2๋Š” 3-4 index์˜ ์ตœ์†Œ๊ฐ’์„ ๊ฐ๊ฐ ๋ฐ›์•„์˜ค๋ฏ€๋กœ ๊ทธ๋ฆผ์˜ 2๋ฒˆ์งธ ์ธต์„ ์˜๋ฏธํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„˜๊ฒจ์ง€๋Š” node ๊ฐ’๋„ ์ด์— ๋งž์ถฐ ๋ฐ”๋€Œ์—ˆ๋‹ค.

m1์œผ๋กœ ๊ฐ€์„œ 0-2๋Š” ๋˜ if๋ฌธ 2๊ฐœ๋ฅผ ํ†ต๊ณผํ•ด์„œ m1์ด 0-1, m2๊ฐ€ 2๋กœ ์ฃผ์–ด์ง„๋‹ค.

๋‹ค์‹œ m1์œผ๋กœ ๋“ค์–ด๊ฐ€๋ฉด m1์ด 0-0, m2๊ฐ€ 1-1๋กœ ๋‚˜๋‰˜์–ด ๊ฐ๊ฐ m1์€ ๋ฒ”์œ„์— ์†ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ -1, m2๋Š” ๋ฒ”์œ„์— ์†ํ•˜๋ฏ€๋กœ index 1์˜ ๊ฐ’์ด return ๋œ๋‹ค. (๋งจ ์•„๋ž˜์ชฝ ์™ผ์ชฝ์˜ ์ฃผํ™ฉ์ƒ‰ 1 ๋…ธ๋“œ) m1,m2 ๊ฐ’์ด return ๋˜์—ˆ์œผ๋ฏ€๋กœ ์•„๋ž˜์˜ if ๋ฌธ์„ ํ†ตํ•ด์„œ ๋น„๊ตํ•ด๋ณด๋ฉด m1์ด -1์ด๋ฏ€๋กœ m2 ๊ฐ’์„ returnํ•˜๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์œ„์—์„œ m1์€ index 1์˜ ๊ฐ’์ด๊ณ , m2๋Š” 2๊ฐ€ ํ•ด๋‹น ๋ฒ”์œ„์— ์†ํ•˜๋ฏ€๋กœ index 2์˜ ๊ฐ’์ธ๋ฐ ๋‘˜๋‹ค -1์ด ์•„๋‹ˆ๋ฏ€๋กœ if๋ฌธ์˜ 2๊ฐœ์˜ ์กฐ๊ฑด์„ ํ†ต๊ณผํ•˜๊ณ  ๋งˆ์ง€๋ง‰ else ๋ฌธ์—์„œ 1๊ณผ 2 ์ค‘ ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์—์„œ ๋” ์ž‘์€ ์ˆ˜๋ฅผ ๊ฐ€์ง„ index๊ฐ€ return ๋œ๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€ ํ•˜๋ฉด ์ฒซ๋ฒˆ์งธ ๋ฌธ๋‹จ์—์„œ m1์„ ๊ตฌํ•œ ๊ฒƒ์ด๋‹ค. ์ด๋Š” 1-2 ๋ฒ”์œ„์˜ ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•œ ๊ฒƒ์ด๊ณ  ๋˜‘๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ m2๋„ ๊ตฌํ•˜๋ฉด m2๋Š” query ํ•จ์ˆ˜์˜ 2๋ฒˆ์งธ if๋ฌธ์— ํ•ด๋‹นํ•˜๋ฏ€๋กœ ํ•ด๋‹น ๋…ธ๋“œ์— ์žˆ๋Š” index๋ฅผ ๋ฐ”๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ด ๋‘˜์„ ๋น„๊ตํ•ด์„œ ๋งˆ์ง€๋ง‰ ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•˜๊ฒŒ ๋œ๋‹ค.

๋ฐ˜์‘ํ˜•