ABOUT ME

-

  • ๐ŸŒฒ Segment Tree 1 - Segment Tree๋ž€?
    ALicademy ๐Ÿ‘ฉโ€๐Ÿซ๐Ÿ‘จโ€๐Ÿซ/์•Œ๊ณ ๋ฆฌ์ฆ˜ 2020. 8. 31. 16:33

    ์›๋ณธ์€ ๋งํฌ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜ƒ

     

    Intro ๐Ÿš€

    ์Šค๋งˆํŠธํฐ์„ ์ผœ์„œ SNS๋ฅผ ๋“ค์–ด๊ฐ€๋ด…์‹œ๋‹ค. ์ง€๋‚œ ํ•œ ๋‹ฌ ๋™์•ˆ ์—ฌ๋Ÿฌ๋ถ„์ด ๋ฐ›์€ ์ข‹์•„์š”๐Ÿ‘ ์˜ ํ•ฉ์„ ๊ตฌํ•˜๊ณ  ์‹ถ์œผ๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋ ๊นŒ์š”?

    ์•„๋งˆ ์—ฌ๋Ÿฌ๋ถ„์ด ์ €์™€ ๋น„์Šทํ•˜๋‹ค๋ฉด ๊ฐ€์žฅ ๋จผ์ € '๋ชจ๋“  ๊ฒŒ์‹œ๋ฌผ ์ค‘ ์ง€๋‚œ ํ•œ ๋‹ฌ ๋™์•ˆ์˜ ๊ฒŒ์‹œ๋ฌผ์—์„œ ๋ฐ›์€ ์ข‹์•„์š” ์ˆ˜๋ฅผ ์ผ์ผ์ด ๋”ํ•˜๋ฉด ๋˜์ง€ ์•Š์„๊นŒ์š”?' ๋ผ๊ณ  ๋ง์”€ํ•˜์‹ค์ง€๋„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.

    ์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๊ฒŒ์‹œ๋ฌผ์˜ ์ˆ˜๊ฐ€ n๊ฐœ์ด๊ณ  ํŠน์ • ๊ธฐ๊ฐ„ ๋™์•ˆ ๋ฐ›์€ ์ข‹์•„์š” ์ˆ˜์˜ ํ•ฉ์„ ๋ฌป๋Š” query๋ฅผ m๊ฐœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(mn)์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•๋„ ๋‚˜์˜์ง€ ์•Š์ง€๋งŒ ๋” ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์€ ์—†์„๊นŒ์š”?

     

    ๊ทธ๋ž˜์„œ ์˜ค๋Š˜ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์šธ ๊ฒƒ์€ ๋ฐ”๋กœ ๊ตฌ๊ฐ„์˜ ํ•ฉ/ ์ฐจ/ ์ตœ๋Œ€๊ฐ’/ ์ตœ์†Œ๊ฐ’ ๋“ฑ์„ ํšจ์œจ์ ์œผ๋กœ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด ์“ฐ์ด๋Š” ์ž๋ฃŒ ๊ตฌ์กฐ์ธ

    ๐ŸŒดSegment Tree๐ŸŒด์ž…๋‹ˆ๋‹ค.

     

    Segment Tree ๐ŸŒด

    Segment Tree๋Š” ๊ฐ ๋…ธ๋“œ๊ฐ€ ๊ตฌ๊ฐ„์„ ๋‚˜ํƒ€๋‚ด๋Š” binary tree์ž…๋‹ˆ๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š” ๋‚˜์ค‘์— query์—์„œ ์š”๊ตฌํ•˜๋Š” ๊ฐ’ ์ฆ‰, ๋Œ€ํ‘œ๊ฐ’์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

     

    ๊ทธ๋ ‡๋‹ค๋ฉด segment tree๋Š” ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„๊นŒ์š”? ๐Ÿค”

    ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” ๊ธธ์ด๊ฐ€ $n$์ธ ๋ฐฐ์—ด arr์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•  ๋•Œ arr๋กœ๋ถ€ํ„ฐ segment tree๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

     

    1. Segment tree์˜ root๋Š” ๋ชจ๋“  ๊ตฌ๊ฐ„ ์ฆ‰, arr[0:nโˆ’1]์—์„œ ์šฐ๋ฆฌ๊ฐ€ ๊ด€์‹ฌ์„ ๊ฐ€์ง€๋Š” data๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    2. Segment tree์˜ ๊ฐ leaf node๋Š” ํ•˜๋‚˜์˜ element๊ฐ€ ๊ฐ€์ง€๋Š” ๋ฒ”์œ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋งํ•ด arr[0]๋ถ€ํ„ฐ arr[nโˆ’1] ๊นŒ์ง€ ๋ชจ๋‘ leaf node์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค.

    3. internal node๋Š” ์ž์‹ ๋…ธ๋“œ ๊ฒฐ๊ณผ๋“ค์„ ์ข…ํ•ฉํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋งํ•ด ๋…ธ๋“œ์˜ ๋Œ€ํ‘œ๊ฐ’์ด ์ตœ๋Œ€๊ฐ’์ด๋ผ๋ฉด internal node๋Š” ์ž์‹ ๋…ธ๋“œ๋“ค ์ค‘ ์ตœ๋Œ€๊ฐ’์„ ์ž์‹ ์˜ ๊ฐ’์œผ๋กœ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

    4. ๊ฐ ์ž๋…€ ๋…ธ๋“œ๋“ค์€ ๋ถ€๋ชจ ๋…ธ๋“œ๊ฐ€ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฒ”์œ„์˜ ๋Œ€๋žต์ ์œผ๋กœ ์ ˆ๋ฐ˜์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    5. n๊ฐœ์˜ element๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•œ segment tree๋Š” ํŽธํ•˜๊ฒŒ 4n์˜ ํฌ๊ธฐ๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์ž์„ธํ•œ ์„ค๋ช…์€ ๋งํฌ ๊ฑธ๋ฆฐ Stack overflow๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.)

    6. Segment tree์˜ root์˜ index๊ฐ€ 1์ผ ๋•Œ ํ•œ ๋…ธ๋“œ์˜ index๊ฐ€ i ๋ผ๋ฉด ์ž์‹ ๋…ธ๋“œ๋“ค์˜ index๋Š” ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ ๊ฐ๊ฐ (2i),(2i+1)์ž…๋‹ˆ๋‹ค. (root์˜ index๊ฐ€ 0์ผ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ์—ฌ๋Ÿฌ๋ถ„๊ป˜์„œ ํ•œ ๋ฒˆ ํ•ด๊ฒฐํ•ด๋ณด์„ธ์š”! ๐Ÿ‘จโ€๐Ÿซ)

    ์ง€๊ธˆ๋ถ€ํ„ฐ๋Š” ๋ณธ๊ฒฉ์ ์œผ๋กœ segment tree๋ฅผ buildํ•˜๊ณ  updateํ•˜๋Š” ๋ฐฉ๋ฒ•, query๋ฅผ ๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ๋ ค๋“œ๋ฆด ๊ฑด๋ฐ ์ดํ•ด๋ฅผ ๋•๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋Œ€ํ‘œ๊ฐ’์ด ๊ตฌ๊ฐ„์—์„œ์˜ ํ•ฉ์ธ segment tree๋ฅผ ์˜ˆ๋กœ ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค.

     

    Build

    segment tree๋Š” ์•ž์„œ ์–ธ๊ธ‰ํ•œ ๋ช‡ ๊ฐ€์ง€ ์„ฑ์งˆ๊ณผ recursion๋งŒ ์ด์šฉํ•˜๋ฉด ์ง๊ด€์ ์ด๊ณ  ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. segment tree๋ฅผ recursiveํ•˜๊ฒŒ ๋งŒ๋“ค ๋•Œ๋Š” bottom up ๋ฐฉ์‹์œผ๋กœ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. ๋‹ค์Œ์€ segment tree๋ฅผ buildํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

     

     

    public void build(long[] tree, long[] arr, int lo, int hi, int idx) {
    if(lo == hi) { // leaf node์— ๊ฐ’์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
    tree[idx] = arr[lo];
    return;
    }
    int mid = lo + (hi - lo) / 2;
    build(tree, arr, lo, mid, 2 * idx); // left child
    build(tree, arr, mid + 1, hi, 2 * idx + 1); // right child
    tree[idx] = tree[2 * idx] + tree[2 * idx + 1]; // merge ํ•ฉ๋‹ˆ๋‹ค.
    }
    view raw build.java hosted with โค by GitHub

     

     

    Update

    ๋งŒ์•ฝ ๋ฐฐ์—ด arr์˜ 2๋ฒˆ์งธ index๊ฐ’์„ 5๋กœ ๋ฐ”๊พธ๋ฉด ์–ด๋–ป๊ฒŒ segment tree๋Š” ์–ด๋–ป๊ฒŒ ๋ฐ”๋€”๊นŒ์š”?

    segment tree์˜ ๋…ธ๋“œ๋“ค ์ค‘ 2๋ฒˆ์งธ index๋ผ๋Š” ๊ตฌ๊ฐ„์„ ํฌํ•จํ•˜๋Š” ๋ชจ๋“  ๋…ธ๋“œ๋“ค์€ ์ˆ˜์ •๋˜์–ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

    ๋‹ค์Œ์€ arr์˜ 2๋ฒˆ์งธ index๊ฐ’์„ 5๋กœ ๋ฐ”๊พธ์—ˆ์„๋•Œ ์˜ํ–ฅ์„ ๋ฐ›๋Š” ๋…ธ๋“œ๋“ค์„ ๋นจ๊ฐ„์ƒ‰ ํ…Œ๋‘๋ฆฌ๋กœ ํ‘œ์‹œํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

     

     

    leaf node๊ฐ€ ์ˆ˜์ •๋˜๋ฉด ๊ทธ ๋…ธ๋“œ๋ฅผ ์ž์‹์œผ๋กœ ๊ฐ–๋Š” ๋ถ€๋ชจ ๋…ธ๋“œ, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋ถ€๋ชจ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋“ค ๋ชจ๋‘ ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.

    ์ด๊ฑธ ๋ณด๋‹ˆ Bottom up ๋ฐฉ์‹์ด ์ƒ๊ฐ๋‚˜๊ณ  Bottom up ๋ฐฉ์‹์„ ์ƒ๊ฐํ•˜๋‹ˆ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฉ๊ธˆ ์‚ดํŽด๋ณธ build ๊ณผ์ •์ด ์ƒ๊ฐ๋‚˜์ง€ ์•Š์œผ์‹œ๋‚˜์š”?

    ๋งŒ์•ฝ ๊ทธ๋Ÿฌ์‹œ๋‹ค๋ฉด ์—ฌ๋Ÿฌ๋ถ„๊ป˜ ๋ฐ•์ˆ˜๋ฅผ ๋ณด๋‚ด๋“œ๋ฆฌ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค! ์ •๋ง ๋Œ€๋‹จํ•˜์‹ญ๋‹ˆ๋‹ค! ๐Ÿ‘๐Ÿ‘๐Ÿ‘

    ์‹ค์ œ๋กœ update๋ฅผ ํ•˜๋Š” ๊ณผ์ •์€ buildํ•˜๋Š” ๊ณผ์ •๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋‹ค์Œ์€ ๊ด€๋ จ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

     

     

    public void update(long[] tree, long target, long value, int lo, int hi, int idx) {
    if(lo == hi) { // leaf node์˜ ๊ฐ’์„ updateํ•ฉ๋‹ˆ๋‹ค.
    tree[idx] = value;
    return;
    }
    int mid = lo + (hi - lo) / 2;
    if(mid >= target) { // ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ ์ž์‹ ์ค‘ ์–ด๋””๋กœ ๊ฐ€์•ผ target์ด ์žˆ๋Š”์ง€ ์ฐพ์Šต๋‹ˆ๋‹ค.
    update(tree, target, value, lo, mid, 2 * idx);
    }
    else {
    update(tree, target, value, mid + 1, hi, 2 * idx + 1);
    }
    tree[idx] = tree[2 * idx] + tree[2 * idx + 1]; // mergeํ•ฉ๋‹ˆ๋‹ค.
    }
    view raw Update.java hosted with โค by GitHub

     

     

    Query

    ๋งŒ์•ฝ segment tree๋ฅผ ์ด์šฉํ•ด arr์˜ 2๋ฒˆ์งธ๋ถ€ํ„ฐ 4๋ฒˆ์งธ index ๊ฐ’์˜ ํ•ฉ์„ ๊ตฌํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋ ๊นŒ์š”?

    segment tree์˜ ๋…ธ๋“œ๊ฐ€ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฒ”์œ„๊ฐ€ 2๋ฒˆ์งธ๋ถ€ํ„ฐ 4๋ฒˆ์งธ ์ธ๋ฑ์Šค์— ์†ํ•˜๋ฉด ๊ทธ ๊ฐ’์„ returnํ•ด์„œ ๋”ํ•˜๋ฉด ์–ด๋–จ๊นŒ์š”?

    ์ฆ‰, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด๋ผ์ƒ‰์œผ๋กœ ์น ํ•œ ๋…ธ๋“œ๋“ค์ด 2๋ฒˆ์งธ๋ถ€ํ„ฐ 4๋ฒˆ์งธ ์ธ๋ฑ์Šค์— ์†ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ฐ’๋“ค์„ returnํ•ด์„œ ๋”ํ•˜๋Š” ๊ฒ๋‹ˆ๋‹ค! ๐Ÿ˜€

     

    Divide & Conquer ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋ฐฉ์‹์ด ์ •๋ง ์•„๋ฆ„๋‹ต์ง€ ์•Š๋‚˜์š”? โœจโœจโœจ

    ๊ฐœ์ธ์ ์œผ๋กœ segment tree์˜ ์•„๋ฆ„๋‹ค์›€์€ ์—ฌ๊ธฐ์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค!

    ๊ด€๋ จ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค!

     

     

    public long query(long[] tree, int from, int to, int lo, int hi, int idx) {
    // [from..to] ๊นŒ์ง€ ํ•ฉ์„ ๊ตฌํ•˜๋Š” query
    if(from > hi || to < lo) return 0; // ๊ตฌ๊ฐ„์„ ์™„์ „ํžˆ ๋ฒ—์–ด๋‚˜๋Š” ๊ฒฝ์šฐ
    if(from <= lo && hi <= to) return tree[idx]; // ๊ตฌ๊ฐ„ ์•ˆ์— ์ •ํ™•ํžˆ ๋“ค์–ด์˜ค๋Š” ๊ฒฝ์šฐ
    int mid = lo + (hi - lo) / 2;
    return query(tree, from, to, lo, mid, 2 * idx) + query(tree, from, to, mid + 1, hi, 2 * idx + 1); // mergeํ•œ๋‹ค.
    }
    view raw Query.java hosted with โค by GitHub

     

     

    Complexity Analysis

    ๋งจ ์ฒ˜์Œ segment tree๋Š” ๊ตฌ๊ฐ„์˜ ํ•ฉ/ ์ฐจ/ ์ตœ๋Œ€๊ฐ’/ ์ตœ์†Œ๊ฐ’ ๋“ฑ์„ ํšจ์œจ์ ์œผ๋กœ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด ์“ฐ์ด๋Š” ์ž๋ฃŒ ๊ตฌ์กฐ๋ผ๊ณ  ํ–ˆ๋Š”๋ฐ ๊ณผ์—ฐ ์–ผ๋งˆ๋‚˜ ํšจ์œจ์ ์ผ๊นŒ์š”? ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ด…์‹œ๋‹ค!

     

    Build

    segment tree๋ฅผ buildํ•˜๋Š” ๊ณผ์ •์„ ์‚ดํŽด๋ด…์‹œ๋‹ค. ์›๋ž˜ ๋ฐ์ดํ„ฐ์˜ ๊ธธ์ด๊ฐ€ n์ด๋ผ๋ฉด segment tree์˜ ๋…ธ๋“œ๋Š” ๋Œ€๋žต์ ์œผ๋กœ 2n๊ฐœ ์ž…๋‹ˆ๋‹ค.

    ์™œ๋ƒํ•˜๋ฉด setment tree์˜ leaf node์—๋Š” ์›๋ž˜ ๋ฐ์ดํ„ฐ์˜ element๋“ค์ด ๋“ค์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— leaf node์˜ ๊ฐœ์ˆ˜๊ฐ€ n๊ฐœ์ด๊ณ  leaf node์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋Š” n2๊ฐœ ์ด๊ธฐ ๋•Œ๋ฌธ์— n+n2+n4+...+1โ‰ˆ2n ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

    ๊ทธ๋ž˜์„œ segment tree๋ฅผ buildํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•ฝ 2n๊ฐœ์˜ ๋…ธ๋“œ๋ฅผ ๋ชจ๋‘ ๋ฐฉ๋ฌธํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(n)์ž…๋‹ˆ๋‹ค!

     

    Update

    updateํ•˜๋Š” ๊ณผ์ •์€ ๋ณด์‹œ๋ฉด ์•„์‹œ๋‹ค์‹œํ”ผ ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ ์ค‘ updateํ•  ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ์ชฝ์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    ์ž˜ ์ƒ๊ฐํ•ด๋ณด๋ฉด ์šฐ๋ฆฐ ์ด๊ฒƒ์ด binary search์™€ ์œ ์‚ฌํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ binary search์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ update ๊ณผ์ •๋„ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O(logโกN) ์ž…๋‹ˆ๋‹ค.

     

    Query

    query๋ฅผ ๊ตฌํ•˜๋Š” ๊ณผ์ •์€ ์–ผ๋งˆ๋‚˜ ๊ฑธ๋ฆด๊นŒ์š”?

    ๋ฏธ๋ฆฌ ๋ง์”€๋“œ๋ฆฌ๋ฉด query๋ฅผ ๊ตฌํ•˜๋Š” ๊ณผ์ •์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O(logN) ์ž…๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    query๋ฅผ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” query์—์„œ ์š”๊ตฌํ•˜๋Š” ๊ตฌ๊ฐ„์— ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜๋Š” ๋…ธ๋“œ๋“ค์„ DFS๋ฅผ ํ†ตํ•ด ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ์ตœ์•…์˜ ๊ฒฝ์šฐ segment tree์˜ leaf node๊นŒ์ง€ ๋ฐฉ๋ฌธํ•ด์•ผ ํ•˜๋Š”๋ฐ ์ด๋Š” segment tree์˜ ๋†’์ด์ธ logN ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ query๋ฅผ ๊ตฌํ•˜๋Š” ๊ณผ์ •์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(logN) ์ž…๋‹ˆ๋‹ค!

     

    Let's do PS ๐Ÿ˜†

    Segment Tree๊ฐ€ ์ž˜ ์ดํ•ด๋˜์…จ๋‚˜์š”?

    ๊ทธ๋ ‡๋‹ค๋ฉด ํ•จ๊ป˜ BOJ 2042๋ฒˆ ๊ตฌ๊ฐ„ ํ•ฉ ๊ตฌํ•˜๊ธฐ 1์„ ํ’€์–ด๋ด…์‹œ๋‹ค!

     

    ๋„์›€์ด ํ•„์š”ํ•˜์‹ค ๋•Œ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!

    ๋”๋ณด๊ธฐ
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    public class BOJ_2042 {
    
    	public static void main(String[] args) throws Exception {
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		String[] inputs = br.readLine().split(" ");
    		int N = Integer.parseInt(inputs[0]);
    		int M = Integer.parseInt(inputs[1]);
    		int K = Integer.parseInt(inputs[2]);
    		
    		long[] arr = new long[N + 1];
    		long[] tree = new long[4 * N];
    		
    		for(int i = 1; i <= N; i++) {
    			arr[i] = Integer.parseInt(br.readLine());
    		}
    		
    		// build
    		build(tree, arr, 1, N, 1);
    		
    		for(int i = 0; i < M + K; i++) {
    			inputs = br.readLine().split(" ");
    			int a = Integer.parseInt(inputs[0]);
    			long b = (long) Double.parseDouble(inputs[1]);
    			long c = (long) Double.parseDouble(inputs[2]);
    			
    			switch(a) {
    			case 1 :
    				//update
    				update(tree, b, c, 1, N, 1);
    				break;
    				
    			case 2 : 
    				// query
    				System.out.println(query(tree, (int) b, (int) c, 1, N, 1));
    				break;
    			}
    		}
    	}
    	
    	public static void build(long[] tree, long[] arr, int lo, int hi, int idx) {
    		if(lo == hi) {
    			tree[idx] = arr[lo];
    			return;
    		}
    		int mid = lo + (hi - lo) / 2;
    		build(tree, arr, lo, mid, 2 * idx);
    		build(tree, arr, mid + 1, hi, 2 * idx + 1);
    		tree[idx] = tree[2 * idx] + tree[2 * idx + 1];
    	}
    	
    	public static void update(long[] tree, long target, long value, int lo, int hi, int idx) {
    		if(lo == hi) {
    			tree[idx] = value;
    			return;
    		}
    		
    		int mid = lo + (hi - lo) / 2;
    		
    		if(mid >= target) {
    			update(tree, target, value, lo, mid, 2 * idx);
    		}
    		else {
    			update(tree, target, value, mid + 1, hi, 2 * idx + 1);
    		}
    		
    		tree[idx] = tree[2 * idx] + tree[2 * idx + 1];
    	}
    	
    	public static long query(long[] tree, int from, int to, int lo, int hi, int idx) {
    		if(from > hi || to < lo) return 0;
    		
    		if(from <= lo && hi <= to) return tree[idx];
    		
    		int mid = lo + (hi - lo) / 2;
    		
    		return query(tree, from, to, lo, mid, 2 * idx) + query(tree, from, to, mid + 1, hi, 2 * idx + 1);
    	}
    
    }

     

    Further Thinking ๐Ÿค”

    ๋งŒ์•ฝ ํŠน์ • ์ธ๋ฑ์Šค๊ฐ€ ์•„๋‹ˆ๋ผ ํŠน์ • ๊ตฌ๊ฐ„์„ updateํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

    ๋ฌผ๋ก  ์šฐ๋ฆฌ๊ฐ€ ์•ž์„œ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋Ÿด ๊ฒฝ์šฐ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ฐฉ๋ฌธํ•˜๋Š” ๋…ธ๋“œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    arr์˜ 1๋ฒˆ์งธ๋ถ€ํ„ฐ 2๋ฒˆ์งธ ์ธ๋ฑ์Šค์˜ ๊ฐ’์„ 1์”ฉ ์ฆ๊ฐ€ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.

    1๋ฒˆ์งธ ์ธ๋ฑ์Šค๋ฅผ updateํ•  ๋•Œ๋Š” 1 โ†’ 2 โ†’ 4 โ†’ 9 ์ˆœ์„œ๋กœ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

     

     

    2๋ฒˆ์งธ ์ธ๋ฑ์Šค๋ฅผ updateํ•  ๋•Œ๋Š” 1 โ†’ 2โ†’ 5 ์ˆœ์„œ๋กœ ๋ฐฉ๋ฌธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

     

    ์ด๋•Œ ์šฐ๋ฆฌ๋Š” 1, 2๋ฒˆ ๋…ธ๋“œ๋Š” ๋‘ ๋ฒˆ ๋ฐฉ๋ฌธํ•œ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์–ด๋–ค ๋ ˆ๋ฒจ์—์„œ๋Š” ๋‹ค๋ฅธ leaf nodef๋กœ '์ „๋‹ฌ'๋˜๋Š” ๋ณ€ํ™”๋“ค์ด ์„œ๋กœ ๋งŒ๋‚˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. update๋˜๋Š” query๊ฐ€ ์ •๋ง ๋งŽ์€ ๊ฒฝ์šฐ ์šฐ๋ฆฌ๋Š” updateํ•˜๊ธฐ ์œ„ํ•ด ๋งŽ์€ ์‹œ๊ฐ„์„ ํ—ˆ๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    ๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋‹ต์€ ๋‹ค์Œ ์‹œ๊ฐ„์— ๋ฐฐ์šธ 'Lazy propagation'์— ์žˆ์Šต๋‹ˆ๋‹ค.

    ๊ทธ๋Ÿผ ๋‹ค์Œ ์‹œ๊ฐ„์— ๋ต™๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿค“

     

    ์ฐธ๊ณ 

    https://leetcode.com/articles/a-recursive-approach-to-segment-trees-range-sum-queries-lazy-propagation/

    https://bowbowbow.tistory.com/4

    https://medium.com/@sivagiri/dissecting-into-segment-trees-ee603a4740d3

    https://stackoverflow.com/questions/28470692/how-is-the-memory-of-the-array-of-segment-tree-2-2-ceillogn-1

    https://en.wikipedia.org/wiki/Segment_tree

     

    ๋Œ“๊ธ€

Designed by Tistory.