문제 링크
https://www.acmicpc.net/problem/2042
문제
어떤 N개의 수가 주어져 있다. 그런데 중간에 수의 변경이 빈번히 일어나고 그 중간에 어떤 부분의 합을 구하려 한다. 만약에 1,2,3,4,5 라는 수가 있고, 3번째 수를 6으로 바꾸고 2번째부터 5번째까지 합을 구하라고 한다면 17을 출력하면 되는 것이다. 그리고 그 상태에서 다섯 번째 수를 2로 바꾸고 3번째부터 5번째까지 합을 구하라고 한다면 12가 될 것이다.
- 입력
- 첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 횟수이고, K는 구간의 합을 구하는 횟수이다. 그리고 둘째 줄부터 N+1번째 줄까지 N개의 수가 주어진다. 그리고 N+2번째 줄부터 N+M+K+1번째 줄까지 세 개의 정수 a, b, c가 주어지는데, a가 1인 경우 b(1 ≤ b ≤ N)번째 수를 c로 바꾸고 a가 2인 경우에는 b(1 ≤ b ≤ N)번째 수부터 c(b ≤ c ≤ N)번째 수까지의 합을 구하여 출력하면 된다.
- 입력으로 주어지는 모든 수는 -2^63보다 크거나 같고, 2^63-1보다 작거나 같은 정수이다.
- 출력
- 첫째 줄부터 K줄에 걸쳐 구한 구간의 합을 출력한다. 단, 정답은 -2^63보다 크거나 같고, 2^63-1보다 작거나 같은 정수이다.
| 예제 입력 | 예제 출력 |
| 5 2 2 1 2 3 4 5 1 3 6 2 2 5 1 5 2 2 3 5 |
17 12 |
강의 영상
코드
import sys
input = sys.stdin.readline
n, m, t = map(int, input().split())
k = 0
length = n
while length != 0:
length //= 2
k += 1
size = 2**k * 2
start_index = 2**k - 1
tree = [0] * (size+1)
for i in range(start_index+1, start_index+n+1):
tree[i] = int(input())
def createTree(i):
while i != 1:
tree[i//2] += tree[i]
i -= 1
createTree(size-1)
def getSum(s, e):
result = 0
while s <= e:
if s % 2 == 1:
result += tree[s]
s += 1
if e % 2 == 0:
result += tree[e]
e -= 1
s //= 2
e //= 2
return result
def update(idx, val):
dv = val - tree[idx]
while idx > 0:
tree[idx] += dv
idx //= 2
for _ in range(m+t):
a, b, c = map(int, input().split())
if a == 1:
update(start_index + b, c)
else:
b += start_index
c += start_index
print(getSum(b, c))
해설
(1) 트리 초기화 단계
- 2^k ≥ N을 만족시키는 k의 최솟값 찾기
- 트리 배열 크기 : 2^k * 2
- 리프 노드 시작 인덱스 : 2^k
- 구간 합 : A[N] = A[2N] + A[2N+1]
(2) 질의값 구하기

start_index % 2 == 1일 때 해당 노드를 선택한다.end_index % 2 ==0일 때 해당 노드를 선택한다.start_index_depth변경 :start_index = (start_index + 1) / 2연산을 실행한다.end_index_depth변경 :end_index = (end_index - 1) / 2연산을 실행한다.- 1~4를 반복하다가
end_index < start_index가 되면 종료한다.
(3) 데이터 업데이트 단계
- 구간 합에서는 원래 데이터와 변경 데이터의 차이만큼 부모 노드로 올라가면서 변경한다.
- 부모 노드로 이동하는 방식은 세그먼트 트리가 이진 트리이므로 index = index / 2로 변경하면 된다.
'PS > 백준' 카테고리의 다른 글
| [백준] (17081) RPG Extreme [Python] (0) | 2025.08.11 |
|---|---|
| [백준] (2583) 영역 구하기 [Python] (0) | 2025.05.18 |
| [백준] (11049) 행렬 곱셈 순서 [Python] (0) | 2025.04.07 |
| [백준] (12865) 평범한 배낭 [Python] (0) | 2025.04.07 |
| [백준] (9252) LCS 2 [Python] (0) | 2025.04.07 |