๊ตฌ๊ฐ„ ํŠธ๋ฆฌ(Segment Tree)

๊ตฌ๊ฐ„ ํŠธ๋ฆฌ ๊ตฌ๊ฐ„ ๋ฒ”์œ„

์ผ์ฐจ์› ๋ฐฐ์—ด์˜ ํŠน์ • ๊ตฌ๊ฐ„์— ๋Œ€ํ•œ ์งˆ๋ฌธ์„ ๋น ๋ฅด๊ฒŒ ๋Œ€๋‹ตํ•˜๋Š” ๋ฐ ํ™œ์šฉ๋˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ

๋Œ€ํ‘œ์ ์œผ๋กœ ๊ตฌ๊ฐ„ ์›์†Œ๋“ค์˜ ํ•ฉ, ๊ตฌ๊ฐ„ ์›์†Œ๋“ค์˜ ์ตœ์†Ÿ๊ฐ’(RMQ, Range Minimum Query) ๋“ฑ์— ๋Œ€ํ•œ ์งˆ์˜๋ฅผ ์ง€์›ํ•œ๋‹ค.

๊ตฌ๊ฐ„ ํŠธ๋ฆฌ ์ดˆ๊ธฐํ™”

  • ๋ฐฐ์—ด์˜ ๊ฐ ๊ตฌ๊ฐ„์„ ํ‘œํ˜„ํ•˜๋Š” ์ด์ง„ ํŠธ๋ฆฌ ํ˜•ํƒœ
  • ๊ตฌ๊ฐ„ ํŠธ๋ฆฌ์˜ ๋ฃจํŠธ๋Š” ๋ฐฐ์—ด์˜ ์ „์ฒด ๊ตฌ๊ฐ„([0, n-1)์„ ํ‘œํ˜„
  • ๊ฐ ํŠธ๋ฆฌ(i)์˜ ์™ผ์ชฝ ์ž์‹(2i)๊ณผ ์˜ค๋ฅธ์ชฝ ์ž์‹(2i+1)์€ ํ•ด๋‹น ๊ตฌ๊ฐ„์„ ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆˆ ์™ผ์ชฝ ๋ถ€๋ถ„์™€ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์„ ํ‘œํ˜„
  • ๋ฆฌํ”„ ๋…ธ๋“œ๋Š” ๊ตฌ๊ฐ„์˜ ํฌ๊ธฐ๊ฐ€ 1์ธ ๊ฒฝ์šฐ
  • ์ „์ฒด ๊ตฌ๊ฐ„ ํฌ๊ธฐ๊ฐ€ 2์˜ ์ œ๊ณฑ๊ผด์ด๋ผ๋ฉด ๋…ธ๋“œ๊ฐ€ 2*(h+1)-1๊ฐœ์ธ ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ๊ฐ€ ์™„์„ฑ๋˜๊ฒ ์ง€๋งŒ, 2์˜ ์ œ๊ณฑ๊ผด์ด ์•„๋‹ˆ๋”๋ผ๋„ ๋‚จ๋Š” ๋…ธ๋“œ๋Š” ๋นˆ ๊ณต๊ฐ„์œผ๋กœ ๋‚จ๊ฒจ๋‘๊ณ  2*(h+1)-1 ํฌ๊ธฐ์˜ ๋ฐฐ์—ด๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด ํŽธํ•จ.
  • ๊ตฌ๊ฐ„ ํŠธ๋ฆฌ์˜ ๊ฐ ๋…ธ๋“œ๋Š” ํ•ด๋‹นํ•˜๋Š” ๊ตฌ๊ฐ„์˜ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•ด๋‘”๋‹ค. ๋”ฐ๋ผ์„œ ์ตœ์†Œ ๊ตฌ๊ฐ„ ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ ๊ฐ ๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’์„, ๊ตฌ๊ฐ„์˜ ํ•ฉ ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ ๊ฐ ๊ตฌ๊ฐ„์˜ ์›์†Œ๋“ค์˜ ํ•ฉ์„ ๋…ธ๋“œ์— ์ €์žฅํ•ด๋‘”๋‹ค.
  • ์–ด๋–ค ๊ตฌ๊ฐ„์ด ์ฃผ์–ด์ง€๋”๋ผ๋„ ํ•ด๋‹น ๊ตฌ๊ฐ„์€ ๊ตฌ๊ฐ„ํŠธ๋ฆฌ ๋…ธ๋“œ์— ํฌํ•จ๋œ ๊ตฌ๊ฐ„๋“ค์˜ ํ•ฉ์ง‘ํ•ฉ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ตฌ๊ฐ„ ํŠธ๋ฆฌ ์งˆ์˜

๊ตฌ๊ฐ„ ํŠธ๋ฆฌ-๊ตฌ๊ฐ„ ์ตœ์†Œ, ๊ตฌ๊ฐ„ ํ•ฉ

๊ตฌ๊ฐ„ ํŠธ๋ฆฌ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ๋ฌธ์ œ์ธ ๊ตฌ๊ฐ„ ์ตœ์†Œ ๋ฌธ์ œ(RMQ, Range Minimum Query)๋ฅผ ๋ณด์ž.

์›๋ฆฌ

์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ํฌํ•จํ•˜๋Š” ๊ตฌ๊ฐ„ ์ง‘ํ•ฉ ์ค‘ ์ง‘ํ•ฉ์˜ ํฌ๊ธฐ๊ฐ€ ์ตœ์†Œ์ธ ๊ตฌ๊ฐ„์„ ์ฐพ๋Š”๋‹ค.

  1. ๋งŒ์•ฝ ํ˜„์žฌ ๊ตฌ๊ฐ„์ด ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ์ „ํ˜€ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ฌดํ•œ๋Œ€๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  2. ๋งŒ์•ฝ ํ˜„์žฌ ๊ตฌ๊ฐ„์ด ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์— ์™„์ „ํžˆ ํฌํ•จ๋œ๋‹ค๋ฉด ํ˜„์žฌ ๋…ธ๋“œ(๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ €์žฅํ•œ ์ƒํƒœ)๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  3. ์œ„์˜ ๋‘ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ(์ฆ‰, ํ˜„์žฌ ๊ตฌ๊ฐ„์ด ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ํฌํ•จํ•˜๋˜ ์ „๋ถ€๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์•„๋‹ˆ๋ฉด ์ตœ์†Œ ํฌ๊ธฐ๊ฐ€ ๋ณด์žฅ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ)์—๋Š” ํ˜„์žฌ ๊ตฌ๊ฐ„์„ ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆ  ์œ„์˜ ๊ณผ์ •์„ ๋‹ค์‹œ ๋ฐ˜๋ณตํ•˜๊ณ  ๋‚œ ๋’ค ๊ฒฐ๊ณผ ์ค‘ ์ตœ์†Ÿ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์‹œ๊ฐ„ ๋ณต์žก๋„

๊ตฌ๊ฐ„ ํŠธ๋ฆฌ์˜ ๋ ˆ๋ฒจ์€ O(log n)์ด๋ฉฐ ์งˆ์˜๋ฅผ ์œ„ํ•ด ์ตœ๋Œ€ ๊ตฌ๊ฐ„ ํŠธ๋ฆฌ์˜ ๋ ˆ๋ฒจ ๋งŒํผ ํ™•์ธํ•˜๋ฉด ๋˜๋ฏ€๋กœ O(log n)์˜ ์—ฐ์‚ฐ์ด ํ•„์š”ํ•˜๋‹ค.

๊ตฌํ˜„

class SegmentTreeRMQ
{
    static int sTree[];        // ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ
    
    // ๋‘ ๊ฐ’์„ ๋น„๊ตํ•ด ๋” ์ž‘์„ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
    static int minVal(int x, int y) {
    	return (x < y) ? x : y;
    }
    
    // ๊ตฌ๊ฐ„์˜ ์ค‘๊ฐ„ ์œ„์น˜๋ฅผ ์ธ๋ฑ์Šค๋กœ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜
    static int getMid(int s, int e) { 
    	return (s + e) / 2;
    }
    
    // ์ฃผ์–ด์ง„ ๋ฐฐ์—ด(์ „์ฒด ๊ตฌ๊ฐ„)์— ๋งž๋Š” ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ ๋งŒ๋“ค๊ธฐ
    static void treeInit(int arr[], int n) {
    	// ํŠธ๋ฆฌ์˜ ๋†’์ด
    	int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
    	// ํŠธ๋ฆฌ ์ตœ๋Œ€ ํฌ๊ธฐ (์ด๋ ‡๊ฒŒ ์ง์ ‘ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๊ณ  n*4๋ฅผ ํ•˜๊ฒŒ๋˜๋ฉด ์‰ฝ๊ฒŒ ๋ชจ๋“  ๋ฐฐ์—ด ์›์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ)
    	int max_size = 2 * (int) Math.pow(2, x) - 1;
    	sTree = new int[max_size];
    
    	// ์ƒ์„ฑํ•œ ํŠธ๋ฆฌ์— ๋ฐฐ์—ด์˜ ์›์†Œ ์‚ฝ์ž…
    	nodeInit(arr, 0, n-1, 1);
    }
    
    // ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ ์ดˆ๊ธฐํ™”(๊ฐ ๋…ธ๋“œ์— ๊ฐ ๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ €์žฅ)
    static int nodeInit(int arr[], int arrStart, int arrEnd, int node) {
    	// ๋ฆฌํ”„๋…ธ๋“œ ํ˜น์€ ์ž์‹ ๋…ธ๋“œ๋“ค์ด ์ด๋ฏธ ๊ฐ์ž ๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’์„ ๊ณ„์‚ฐํ•˜์—ฌ ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ 
    	if (arrStart == arrEnd) return sTree[node] = arr[arrStart];
    
    	// ๊ตฌ๊ฐ„์„ ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆ ๊ฐ€๋ฉฐ ์žฌ๊ท€์ ์œผ๋กœ ์ž์‹ ๋…ธ๋“œ๋“ค์— ๊ฐ ๋…ธ๋“œ๊ฐ€ ํฌํ•จํ•˜๋Š” ๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ €์žฅ
    	int mid = getMid(arrStart, arrEnd);
    	return sTree[node] = minVal(nodeInit(arr, arrStart, mid, 2*node), nodeInit(arr, mid+1, arrEnd, 2*node+1));
    }
    
    // ๊ตฌ๊ฐ„ ์ตœ์†Œ๋ฅผ ๊ตฌํ•˜๋Š” ๋ฉ”์„œ๋“œ
    static int RMQ(int treeStart, int treeEnd, int queryStart, int queryEnd, int node) {
    	// ํ˜„์žฌ ๋…ธ๋“œ์— ํ‘œํ˜„๋œ ๊ตฌ๊ฐ„์ด ํƒ์ƒ‰์„ ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ์™„์ „ํžˆ ๋ฐฐ์ œํ•œ๋‹ค๋ฉด ๋ฌดํ•œ๋Œ€ ๋ฐ˜ํ™˜
    	if (treeStart > queryEnd || treeEnd < queryStart) return Integer.MAX_VALUE;
    
    	// ํ˜„์žฌ ๋…ธ๋“œ์— ํ‘œํ˜„๋œ ๊ตฌ๊ฐ„์ด ํƒ์ƒ‰์„ ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์— ํฌํ•จ๋œ๋‹ค๋ฉด ๋…ธ๋“œ(๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’)์— ์ €์žฅ๋œ ๊ฐ’ ๋ฐ˜ํ™˜
    	if (queryStart <= treeStart && queryEnd >= treeEnd) return sTree[node];
    
    	// ํ˜„์žฌ ๋…ธ๋“œ์— ํ‘œํ˜„๋œ ๊ตฌ๊ฐ„์ด ํƒ์ƒ‰์„ ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ์ผ๋ถ€ ํฌํ•จํ•  ๊ฒฝ์šฐ ํ˜„์žฌ ๊ตฌ๊ฐ„์„ ์™ผ์ชฝ ๋ถ€๋ถ„์™€ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ  ๋‹ค์‹œ ์งˆ์˜
    	int mid = getMid(treeStart, treeEnd);      // ํ˜„์žฌ ๋…ธ๋“œ์˜ ๊ตฌ๊ฐ„์„ ๋‚˜๋ˆ”
    	// ์™ผ์ชฝ ๊ตฌ๊ฐ„์— ๋Œ€ํ•ด ์งˆ์˜ํ•œ ๊ฒฐ๊ณผ์™€ ์˜ค๋ฅธ์ชพ ๊ตฌ๊ฐ„์— ๋Œ€ํ•ด ์งˆ์˜ํ•œ ๊ฒฐ๊ณผ ์ค‘ ์ตœ์†Ÿ๊ฐ’์„ ์ฑ„ํƒ
    	return minVal(RMQ(treeStart, mid, queryStart, queryEnd, 2*node), RMQ(mid+1, treeEnd, queryStart, queryEnd, 2*node+1));
    }
    
    public static void main(String args[]) {
    	int arr[] = {1, 3, 2, 7, 9, 11};
    
    	// ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์— ๋งž๋Š” ํŠธ๋ฆฌ ์ƒ์„ฑ
    	treeInit(arr, arr.length);
    
    	int queryStart = 2;    // ํƒ์ƒ‰ ์›ํ•˜๋Š” ๊ตฌ๊ฐ„ ์‹œ์ž‘ ์ง€์ 
    	int queryEnd = 3;      // ํƒ์ƒ‰ ์›ํ•˜๋Š” ๊ตฌ๊ฐ„ ์ข…๋ฃŒ ์ง€์ 
    
    	System.out.println(
    	"Minimum of values in range [" + queryStart + ", " + queryEnd + "] is = " + RMQ(0, arr.length-1, queryStart, queryEnd, 1));
    }
}

๋งŒ์•ฝ ๊ตฌ๊ฐ„ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ๋กœ ๋ฐ”๊พธ์–ด ํ’€๊ณ ์‹ถ๋‹ค๋ฉด nodeInit() ๋ฉ”์„œ๋“œ์—์„œ ๊ฐ ๋…ธ๋“œ์— ๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ €์žฅํ•˜์ง€ ๋ง๊ณ  ๊ตฌ๊ฐ„ํ•ฉ์„ ๊ณ„์‚ฐํ•ด์„œ ์ €์žฅํ•˜๋ฉด ๋œ๋‹ค.

public class SegmentTreeSum {
	static int N, M, K;
	static long[] sTree, arr;
		
	public static long initNode(int start, int end, int node) {
		if(start == end) return sTree[node] = arr[start];	
		
		int mid = (start + end)/2;
		return sTree[node] = initNode(start, mid, node*2)
				    	   + initNode(mid+1, end, node*2+1);
	}
	
	public static long sum(int tStart, int tEnd, int qStart, long qEnd, int node) {
		if (qEnd<tStart || qStart>tEnd) return 0;
		
		if (qStart<=tStart && qEnd>=tEnd) return sTree[node];
		
		int mid = (tStart+tEnd)/2;
		return sum(tStart, mid, qStart, qEnd, 2*node) 
			 + sum(mid+1, tEnd, qStart, qEnd, 2*node+1);
	}
	
	public static void update(int start, int end, int node, int idx, long value) {
		if (idx<start || idx>end) return;
		
		sTree[node] += value;
		if (start==end) return;
		
		int mid = (start+end)/2;
		update(start, mid, 2*node, idx, value);
		update(mid+1, end, 2*node+1, idx, value);
	}
}

๊ตฌ๊ฐ„ ํŠธ๋ฆฌ ๊ฐฑ์‹ 

๊ตฌ๊ฐ„ ํŠธ๋ฆฌ ์ดˆ๊ธฐํ™” ๋‹จ๊ณ„์—์„œ ์ฃผ์–ด์ง„ ๋ฐฐ์—ด๋Œ€๋กœ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ดํ›„ ๋ฐฐ์—ด์˜ ์›์†Œ๋ฅผ ๋ฐ”๊พธ์–ด ํŠธ๋ฆฌ์— ๋‹ค์‹œ ๋ฐ˜์˜ํ•ด์•ผํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ตฌ๊ฐ„ ํŠธ๋ฆฌ๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋ณด์ž.

์›๋ฆฌ

์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ํฌํ•จํ•˜๋Š” ๊ตฌ๊ฐ„ ์ง‘ํ•ฉ ์ค‘ ์ง‘ํ•ฉ์˜ ํฌ๊ธฐ๊ฐ€ ์ตœ์†Œ์ธ ๊ตฌ๊ฐ„์„ ์ฐพ๋Š”๋‹ค.

  1. ๋งŒ์•ฝ ํ˜„์žฌ ๊ตฌ๊ฐ„์ด ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ์ „ํ˜€ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด pass
  2. ๋งŒ์•ฝ ํ˜„์žฌ ๊ตฌ๊ฐ„์ด ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์— ์™„์ „ํžˆ ํฌํ•จ๋œ๋‹ค๋ฉด ํ˜„์žฌ ๋…ธ๋“œ์˜ ๊ฐ’์„ ๊ฐฑ์‹ ํ•œ๋‹ค.
  3. ์œ„์˜ ๋‘ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ(์ฆ‰, ํ˜„์žฌ ๊ตฌ๊ฐ„์ด ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ํฌํ•จํ•˜๋˜ ์ „๋ถ€๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์•„๋‹ˆ๋ฉด ์ตœ์†Œ ํฌ๊ธฐ๊ฐ€ ๋ณด์žฅ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ)์—๋Š” ํ˜„์žฌ ๊ตฌ๊ฐ„์„ ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆ  ์œ„์˜ ๊ณผ์ •์„ ๋‹ค์‹œ ๋ฐ˜๋ณตํ•˜๋ฉฐ ๊ฐ’์„ ๊ฐฑ์‹ ํ•œ๋‹ค.

์‹œ๊ฐ„ ๋ณต์žก๋„

๋ณ€๊ฒฝ์„ ์›ํ•˜๋Š” ์›์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ตฌ๊ฐ„์€ ๊ตฌ๊ฐ„ ํŠธ๋ฆฌ์— O(log n)๊ฐœ ์กด์žฌํ•˜๋ฏ€๋กœ ํŠน์ • ์›์†Œ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ๋„ O(log n)๋งŒํผ์˜ ์—ฐ์‚ฐ๋งŒ ์ˆ˜ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

๊ตฌํ˜„

void updateTree(int[] arr, int treeStart, int treeEnd, int node, int index, int diff) {
    // ํ˜„์žฌ ๋…ธ๋“œ์— ํ‘œํ˜„๋œ ๊ตฌ๊ฐ„์ด ํƒ์ƒ‰์„ ์›ํ•˜๋Š” ๊ตฌ๊ฐ„์„ ์™„์ „ํžˆ ๋ฐฐ์ œํ•œ๋‹ค๋ฉด pass
    if (treeStart > index || treeEnd < index) return;

    // ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ๋ฐฐ์—ด ์›์†Œ์™€ ํ•ด๋‹น ์›์†Œ ๋ณ€ํ™”๊ฐ€ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๋ชจ๋“  ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝ(์ตœ์†Ÿ๊ฐ’ ๋ณ€๊ฒฝ)
    sTree[node] += diff;
    
    // ์ตœ์ข… ๋ฐฐ์—ด ์›์†Œ๊นŒ์ง€ ๊ฐ’์„ ๋ณ€๊ฒฝํ–ˆ๋‹ค๋ฉด ์žฌ๊ท€ ์ข…๋ฃŒ
    if (start == end) return;
    
    // ๊ฐ’์˜ ๋ณ€๊ฒฝ์„ ์›ํ•˜๋Š” ์›์†Œ๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋“  ๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’์„ ๋ฐ”๊ฟ”์ฃผ๊ธฐ ์œ„ํ•ด ์žฌ๊ท€์ ์œผ๋กœ ํƒ์ƒ‰
    int mid = getMid(treeStart, treeEnd);      // ํ˜„์žฌ ํŠธ๋ฆฌ์˜ ๊ตฌ๊ฐ„์„ ๋‚˜๋ˆ”
    // ๊ฐ’์˜ ๋ณ€๊ฒฝ์„ ์›ํ•˜๋Š” ์›์†Œ๊ฐ€ ํฌํ•จ๋œ ๊ตฌ๊ฐ„์˜ ์ตœ์†Ÿ๊ฐ’์„ ๋ชจ๋‘ ๋ฐ”๊ฟ”์คŒ
    updateTree(arr, treeStart, mid, 2*node, index, diff);
    updateTree(arr, mid+1, treeEnd, 2*node+1, index, diff);
}