Search

세그먼트 트리 [개념]

생성일
2025/02/14
URL

1. 세그먼트 트리란?

세그먼트 트리(Segment Tree)는 구간의 합, 최솟값, 최댓값 등을 빠르게 구할 때 사용하는 자료구조이다.
세그먼트 트리 vs 누적합 비교

2. 트리 만들기

위와 같은 숫자들의 구간 합을 구하기 위해서 2개씩 합계를 구한다.
2개의 합계를 또 2개씩 묶는다.
이번에도 또 2개씩 묶는다. 문제는 앞의 2개를 묶으면 하나가 남는다. 이럴 때에는 뒤에 0으로 되어있는 합계가 있다고 생각하면 된다.
마지막으로 2개의 합계를 구하면 세그먼트 트리가 완성된다.

3. 구간 합 구하기

이제 4번째 숫자인 4부터 11번째 숫자인 11까지의 합계를 구해보자.
먼저, 전체 범위인 1부터 16까지를 확인한다. 4부터 11까지이기 때문에 범위를 줄여줄 필요가 있다.
따라서, 이분 탐색처럼 두 부분으로 나누어 다시 탐색한다.
1부터 8까지 범위 확인 결과 아직 4와 11 범위 밖의 값이 존재하기 때문에 한 단계 안으로 더 들어간다.
9부터 16까지 범위 확인 결과 아직 4와 11 범위 밖의 값이 존재하기 때문에 마찬가지로 더 들어간다.
1부터 4까지 범위 안에는 4가 포함 되어 있기 때문에 한 단계 더 들어간다.
5부터 8까지는 전체 구하려는 범위인 4와 11 사이 범위에 포함되어 있기 때문에 더 이상 탐색할 필요가 없다.
9부터 12까지는 구하려는 범위 11보다 크기 때문에 한 단계 더 들어간다.
13부터 16은 범위 밖에 있기 때문에 더 이상 탐색할 필요가 없다.
1부터 2는 범위 밖에 있기 때문에 더 이상 탐색할 필요가 없다.
3부터 4는 3이 범위 밖에 있기 때문에 한 단계 더 들어간다.
이미 범위 안을 확인했던 5부터 8은 넘어간다.
9부터 10은 범위 안에 있기 때문에 포함한다.
11부터 12는 12가 범위 밖에 있기 때문에 한 단계 더 들어간다.
최종적으로 모든 범위를 구했다. 이제 4 + 32 + 9 + 11을 하면 4부터 11까지의 범위의 합계를 구할 수 있다.
그림으로 쉽게 표현 하였지만 각각의 위치를 구하는 것도 쉽지 않다. 아래부터 1번 인덱스로 하는 트리 형태를 떠올려야 한다.
전체 범위의 값은 1번 인덱스에 저장된다.
1번 부터 8번까지는 2번 인덱스가 된다.
9번부터 16번 인덱스는 3번 인덱스가 된다.
어떤 범위가 n번 인덱스라면 그 하위 인덱스는 2n과 2n + 1번 인덱스가 된다.
여기서는 전체가 16개의 범위를 뜻하지만 데이터의 개수에 따라 전체의 범위가 변한다.
데이터가 4개라면 전체가 1부터 4까지가 되는 것이고
데이터가 100개라면 전체 범위는 데이터 100개를 포함할 수 있는 2의 제곱수인 128개가 된다.

3. 값 업데이트 하기

누적합을 사용해서 구간합을 구하는 것은 세그먼트 트리보다 빠를 수 있다.
하지만 값의 변경이 생긴다면 누적합으로는 해결이 불가능 하다.
어떤 값이 변경될 때마다 매번 누적합을 다시 구해줘야 하기 때문이다.
하지만, 세그먼트 트리를 이용하면 몇 개의 숫자만 변경하면 된다.
첫 번째 값인 10을 15로 변경해보자. 값이 10에서 15로 5가 커졌다.
10이 포함된 라인의 값 모두에 5씩 더해주면 된다.
이렇게 자신이 포함된 상위 노드의 숫자들만 5씩 크게 만들면 문제가 해결된다.
중간의 7번째 인덱스의 값인 7을 3으로 변경해보자. 7보다 4 작아졌기 때문에 다음과 같이 해당 라인의 숫자들만 변경해주면 된다.

4. 관련 문제

참고 자료