Notice
Recent Posts
Recent Comments
Today
Total
05-22 07:59
Link
๊ด€๋ฆฌ ๋ฉ”๋‰ด

Partially Committed

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ (Java, Segment tree) ๋ณธ๋ฌธ

๐Ÿ”ฅ Algorithm || ๋ฌธ์ œํ’€์ด/PS

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ (Java, Segment tree)

WonderJay 2023. 8. 9. 12:32
728x90
๋ฐ˜์‘ํ˜•
SMALL

๊ธฐ์—… ์ฝ”ํ…Œ์—์„œ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์š”๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ํ”์น˜ ์•Š์€ ๊ฒƒ ๊ฐ™์ง€๋งŒ

 

ํ•„์š”ํ•œ ์ผ์ด ์ƒ๊ฒจ์„œ

 

์ด์ฐธ์— ์ •๋ฆฌํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค..

 

๊ฐ’์ด ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ,

 

๊ตฌ๊ฐ„ ํ•ฉ์„ ๋น ๋ฅด๊ฒŒ ๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€   

 

prefix sum ์„ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

https://www.crocus.co.kr/843

 

๊ตฌ๊ฐ„ ํ•ฉ(Prefix Sum) ์•Œ๊ณ ๋ฆฌ์ฆ˜

๋ชฉ์ฐจ 1. ๊ตฌ๊ฐ„ ํ•ฉ(Prefix Sum)์ด๋ž€? 2. ๊ตฌ๊ฐ„ ํ•ฉ(Prefix Sum)์ด ์–ด๋””์— ์“ฐ์ผ๊นŒ? 3. Prefix Sum Algorithm 4. Prefix Sum์ด ์“ฐ์ด๋Š” ๋ฌธ์ œ๋“ค 1. ๊ตฌ๊ฐ„ ํ•ฉ(Prefix Sum)์ด๋ž€? ๊ณต๋ถ€๋ฅผ ํ•˜๋‹ค๋ณด๋ฉด ๋ถ€๋ถ„ ํ•ฉ, ๊ตฌ๊ฐ„ ํ•ฉ์˜ ๊ฐœ๋…์ด ํ—ท๊ฐˆ๋ฆด ๋•Œ

www.crocus.co.kr

 

๋งŒ์•ฝ, ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€ํ•œ๋‹ค๋ฉด Fenwick tree ๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ๊ตฌ๊ฐ„ ์ฟผ๋ฆฌ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

https://yabmoons.tistory.com/438

 

[ ํŽœ์œ…ํŠธ๋ฆฌ(FenwickTree) ] ๊ฐœ๋…๊ณผ ๊ตฌํ˜„๋ฐฉ๋ฒ• (C++)

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ํŽœ์œ…ํŠธ๋ฆฌ(FenwickTree) ์— ๋Œ€ํ•ด์„œ ์ด์•ผ๊ธฐํ•ด๋ณด์ž. ์ด ๊ธ€์„ ์ฝ๊ธฐ ์ „์— ๋จผ์ € '์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ'์— ๋Œ€ํ•œ ๊ธ€์„ ์ฝ๊ณ  ์˜ค๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ๋ชจ๋ฅธ๋‹ค๊ณ  ํ•ด์„œ ํŽœ์œ…ํŠธ๋ฆฌ๋ฅผ ์ ˆ๋Œ€ ์ด

yabmoons.tistory.com

 

ํ•˜์ง€๋งŒ ๊ตฌ๊ฐ„์— ๋Œ€ํ•œ ํŠน์ • ๊ฐ’์„ ๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ํŽœ์œ… ํŠธ๋ฆฌ๋ฅผ ์ด์šฉํ•ด์„œ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด ๊ตฌ๊ฐ„ [A, B] ์—์„œ์˜ ์ตœ๋Œ“๊ฐ’, ์ตœ์†Ÿ๊ฐ’, gcd, lcm, ๋“ฑ๋“ฑ

 

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์œ ๋ฆฌํ•˜๋‹ค. (ํŽœ์œ… ํŠธ๋ฆฌ๋ณด๋‹ค ์š”๊ตฌํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋” ๋งŽ๊ธด ํ•จ)

 

๊ตฌ๊ฐ„ ์ฟผ๋ฆฌ๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ, 

 

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ด์šฉํ•˜๋ฉด 

 

์ฟผ๋ฆฌ ์—ฐ์‚ฐ๊ณผ ์—…๋ฐ์ดํŠธ ์—ฐ์‚ฐ์„ log(N) ์— ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

โš ๏ธ ํ•˜์ง€๋งŒ Range update ์— ๋Œ€ํ•ด์„œ๋Š” ๋น„ํšจ์œจ์ ์ด๋‹ค. M ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ตฌ๊ฐ„์— ์ผ๊ด„์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด ๊ธฐ์กด์˜ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ์—์„œ๋Š” M*log(N) ์ด ํ•„์š”ํ•˜๋‹ค. Range update ๊ฐ€ ๋งŽ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ํฐ ๋ฌธ์ œ๊ฐ€ ์—†๊ฒ ์ง€๋งŒ, ๋งŒ์•ฝ Range update ๊ฐ€ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ํ™˜๊ฒฝ์ด๋ผ๋ฉด Lazy propagation ์ด๋ผ๋Š” ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•ด์•ผ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ณธ ํฌ์ŠคํŒ…์—์„œ๋Š” ๊ทธ ๊ฒฝ์šฐ๊นŒ์ง€๋Š” ๊ณ ๋ คํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

์„ค๋ช…์€ ์•„๋ž˜์— ์ฃผ์„์œผ๋กœ ๋Œ€์ฒดํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

public static class segmentTree {
        long[] tree; // ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ ๊ฐ’์ด ์ €์žฅ๋  ๋ฐฐ์—ด
        int N; // ์›๋ณธ ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜

        public segmentTree(int n, int[] arr) { // ์ƒ์„ฑ์ž
            N = n;
            tree = new long[n * 4]; // ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ๋Š” 2N <= x <4N ์ด ๋ณด์žฅ๋œ๋‹ค. (top-down)
            build(arr, 1, 0, n - 1); // init
        }

        private long build(int[] arr, int node, int nodeLeft, int nodeRight) {
            if (nodeLeft == nodeRight) { // leaf ์— ๋„๋‹ฌํ•œ ๊ฒฝ์šฐ์— ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค.
                return tree[node] = arr[nodeLeft];
            }
            int mid = nodeLeft + (nodeRight - nodeLeft) / 2; // overflow ๋ฐฉ์ง€
            // (a+b)/2 ๋ผ๊ณ  ํ•˜๋ฉด (a+b) ์—์„œ Long overflow ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
            long leftVal = build(arr, node * 2, nodeLeft, mid); 
            long rightVal = build(arr, node * 2 + 1, mid + 1, nodeRight);
            return tree[node] = merge(leftVal, rightVal);
        }

        public long merge(long left, long right) {
            return left + right; // sum
            // return Math.min(left, right); // min
            // return Math.max(left, right); // max
        }

        public Long query(int left, int right) {
            // ์‹ค์ œ ์ž…๋ ฅ ๋ฐฐ์—ด์—์„œ [left, right] ๊ตฌ๊ฐ„์—์„œ์˜ query ๊ฒฐ๊ณผ๊ฐ’ ๋ฐ˜ํ™˜
            return queryRecursive(left, right, 1, 0, N - 1);
        }

        public Long update(int index, int newValue) {
            return updateRecursive(index, newValue, 1, 0, N - 1); // ์žฌ๊ท€์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ
        }

        public Long updateRange(int left, int right, int newValue) { // range update
            return updateRangeRecursive(left, right, newValue, 1, 0, N - 1); 
        }

        private Long queryRecursive(int left, int right, int node, int nodeLeft, int nodeRight) {
            if (right < nodeLeft || nodeRight < left) {
                return 0L; // ํ•ด๋‹น ๋…ธ๋“œ ๋ฏธํฌํ•จ
            }
            if (left <= nodeLeft && nodeRight <= right) {
                return tree[node]; // ํ•ด๋‹น ๋…ธ๋“œ ํฌํ•จ
            }
            int mid = nodeLeft + (nodeRight - nodeLeft) / 2;
            return merge(queryRecursive(left, right, node * 2, nodeLeft, mid),
                    queryRecursive(left, right, node * 2 + 1, mid + 1, nodeRight));
        }

        private Long updateRecursive(int index, int newValue, int node, int nodeLeft, int nodeRight) {
            if (index < nodeLeft || nodeRight < index) {
                return tree[node];
            }
            if (nodeLeft == nodeRight) { // ๋ฆฌํ”„ ๋…ธ๋“œ์— ๋„๋‹ฌํ•˜๋ฉด
                return tree[node] = newValue;
            }
            int mid = nodeLeft + (nodeRight - nodeLeft) / 2;

            Long leftVal = updateRecursive(index, newValue, node * 2, nodeLeft, mid);
            Long rightVal = updateRecursive(index, newValue, node * 2 + 1, mid + 1, nodeRight);

            return tree[node] = merge(leftVal, rightVal);
        }

        private Long updateRangeRecursive(int left, int right, int newValue, int node, int nodeLeft, int nodeRight) {
            if (right < nodeLeft || nodeRight < left) {
                return tree[node];
            }
            if (nodeLeft == nodeRight) {
                return tree[node] = newValue;
            }
            int mid = nodeLeft + (nodeRight - nodeLeft) / 2;
            Long leftVal = updateRangeRecursive(left, right, newValue, node * 2, nodeLeft, mid);
            Long rightVal = updateRangeRecursive(left, right, newValue, node * 2 + 1, mid + 1, nodeRight);
            return tree[node] = merge(leftVal, rightVal);
        }
    }

์ด์ œ ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด์ž.

 

์œ„ ์ฝ”๋“œ๋งŒ ์ˆ™์ง€ํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค!

 

https://www.acmicpc.net/problem/1275

 

1275๋ฒˆ: ์ปคํ”ผ์ˆ2

์ฒซ์งธ ์ค„์— ์ˆ˜์˜ ๊ฐœ์ˆ˜ N๊ณผ ํ„ด์˜ ๊ฐœ์ˆ˜ Q๊ฐ€ ์ฃผ์–ด์ง„๋‹ค.(1 ≤ N, Q ≤ 100,000) ๋‘˜์งธ ์ค„์—๋Š” ์ฒ˜์Œ ๋ฐฐ์—ด์— ๋“ค์–ด๊ฐ€ ์žˆ๋Š” ์ •์ˆ˜ N๊ฐœ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ์„ธ ๋ฒˆ์งธ ์ค„์—์„œ Q+2๋ฒˆ์งธ ์ค„๊นŒ์ง€๋Š” x y a b์˜ ํ˜•์‹์œผ๋กœ x~y๊นŒ์ง€์˜ ํ•ฉ

www.acmicpc.net

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ ์ž์ฒด๊ฐ€ ์กฐ๊ธˆ ๋‚œ์ด๋„๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ ๋ฌธ์ œ์ผ์ง€๋ผ๋„ ๊ณจ๋“œ I ์—์„œ ์‹œ์ž‘ํ•œ๋‹ค.

 

( ๋ฐฑ์ค€ ํ‹ฐ์–ด ์˜ฌ๋ฆฌ๊ธฐ์— ์ข‹์Œ ,,,)

 

 

์—ฌํŠผ ์œ„ ๋ฌธ์ œ๋ฅผ ์ฝ์–ด๋ณด๋ฉด,

 

๋ฌธ์ œ / ์ž…๋ ฅ ์„ค๋ช…

N ๊ฐœ์˜ ์›๋ณธ ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ์–ด์ง€๊ณ  Q ๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค.

 

๊ฐ๊ฐ์˜ ์ฟผ๋ฆฌ๋Š” sum query ๋ฅผ ์ˆ˜ํ–‰ํ•œ ๋’ค update ๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ •์˜๋œ๋‹ค.

 

์œ„์™€ ๊ฐ™์ด ์ž…๋ ฅ์ด ์ฃผ์–ด์ง€๋ฉด, ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜๋Š” 5๊ฐœ ์ด๊ณ  ์ฟผ๋ฆฌ์˜ ๊ฐœ์ˆ˜๋Š” 2๊ฐœ ์ธ ๊ฒƒ.

 

๋ฐ์ดํ„ฐ๋Š” [1, 2, 3, 4, 5] ์ด๊ณ 

 

์ฟผ๋ฆฌ 1. ์—์„œ๋Š” 2~3 ๊นŒ์ง€์˜ ํ•ฉ์„ ๊ตฌํ•˜๊ณ , 3 ๋ฒˆ์จฐ์˜ ๊ฐ’์„ 1 ์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.

์ฟผ๋ฆฌ 2. ์—์„œ๋Š” 3~5 ๊นŒ์ง€์˜ ํ•ฉ์„ ๊ตฌํ•˜๊ณ , 4 ๋ฒˆ์งธ์˜ ๊ฐ’์„ 1 ์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.

 

์ฃผ์˜ํ•  ์ ์€, ์ž…์ถœ๋ ฅ์—์„œ ์ฃผ์–ด์ง€๋Š” ์ˆœ์„œ ๊ฐ’๋“ค์€ ์ „๋ถ€ 1-indexed ์ด๊ณ 

 

์šฐ๋ฆฌ๊ฐ€ ๊ตฌํ˜„ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” 0-indexed ๋ผ๋Š” ๊ฒƒ์ด๋‹ค.

 

๋˜ํ•œ ๊ตฌ๊ฐ„ ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ, left ์™€ right ๊ฐ€ ์ฃผ์–ด์ง€๋ฉด left ๊ฐ€ right ๋ณด๋‹ค ํฌ๊ฒŒ ์ฃผ์–ด์ง€๋Š” ๊ฒฝ์šฐ์—๋Š” left ์™€ right ๋ฅผ ๋ฐ”๊พธ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

์œ„์—์„œ ๊ตฌํ˜„ํ•œ segmentTree ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜๋ฉด ๋งค์šฐ ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer stk;
		// ๋ฐฑ์ค€ 1275 ์ปคํ”ผ์ˆ 2 ์†”๋ฃจ์…˜

        stk = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(stk.nextToken()); // ์ˆ˜์˜ ๊ฐœ์ˆ˜
        int Q = Integer.parseInt(stk.nextToken()); // ํ„ด์˜ ๊ฐœ์ˆ˜
        int[] arr = new int[N];

        stk = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) {
            arr[i] = Integer.parseInt(stk.nextToken());
        }

        segmentTree segmentTree = new segmentTree(N, arr);

        for (int i = 0; i < Q; i++) {
            stk = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(stk.nextToken());
            int y = Integer.parseInt(stk.nextToken());

            if (x > y) {
                int t = x;
                x = y;
                y = t;
            }

            int a = Integer.parseInt(stk.nextToken());
            int b = Integer.parseInt(stk.nextToken());

            Long sum = segmentTree.query(x - 1, y - 1);
            segmentTree.update(a - 1, b);
            bw.write(sum + "\n");
        }


        bw.flush();
        bw.close();
    }

 

 

 

 


์ฐธ๊ณ  ์ž๋ฃŒ๋“ค

https://www.crocus.co.kr/648

 

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ(Segment Tree)

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ(Segment Tree)๋Š” ์š”์ฒญํ•˜๋Š” ์ฟผ๋ฆฌ์— ๋Œ€ํ•ด ๋ฐฉ์‹์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์œผ๋‚˜, ๋ชจ๋“  ์ฟผ๋ฆฌ๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์—†๊ธฐ์— ๊ตฌ๊ฐ„ ํ•ฉ์— ๋Œ€ํ•œ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ •๋ฆฌํ•ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด์šฉ์ด ๊ธธ์ง€๋งŒ ๊ทธ๋งŒํผ ์ž์„ธํžˆ ์„ค

www.crocus.co.kr

https://www.youtube.com/watch?v=075fcq7oCC8&t=938s 

 

728x90
๋ฐ˜์‘ํ˜•
LIST
Comments