https://www.acmicpc.net/problem/2042
2042번: 구간 합 구하기
첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 횟수이고, K는 구간의 합을 구하는 횟수이다. 그리고 둘째 줄부터 N+1번째 줄
www.acmicpc.net
세그먼트 트리란?
여러개의 데이터 중에서 특정 구간의 합(곱, 최대, 최솟값 등)을 빠르게 구할 수 있는 자료구조이다.
투 포인터 역시 구간의 합을 구하는 알고리즘이지만 시간복잡도가 O(N) 이므로
똑같은 데이터가 주어지고 탐색을 여러번 반복해야 하는 상황이라면 효율적이지 못하다.
세그먼트 트리는 이진트리 구조를 활용하며 루트 노드(1번 노드) 에는 모든 구간의 합
그 밑의 자식노드(2번 노드, 3번 노드)는 부모 노드의 절반 구간까지의 합을 삽입하는식으로 계속 진행한다.
재귀함수를 이용하면 구현이 간단하며 루트 노드를 1번 노드로 설정하면 부모 노드 * 2가 왼쪽 자식 노드로 이어진다.
노드의 총 개수는 데이터의 개수 * 4로 설정하면 충분하다.
import sys
n,m,k = map(int,sys.stdin.readline().rstrip().split())
lst = [int(sys.stdin.readline().strip()) for _ in range(n)]
tree = [0]*n*4
def init(index,start,last): #범위를 좁혀나가는 식으로 재귀함수 이용 구현
if start >= last:
tree[index] = lst[start-1]
else:
c = int((start+last)/2)
tree[index] = init(index*2,start,c) + init(index*2+1,c+1,last)
return tree[index]
def find(index,start,last,left,right):
if start > right or last < left:
return 0
elif start <= left and last >= right:
return tree[index]
else:
c = int((left+right)/2)
return find(index*2,start,last,left,c) + find(index*2+1,start,last,c+1,right)
def update(d,x,index,start,last):
if x >= start and x <= last:
tree[index] += d
if start != last:
c = int((start+last)/2)
update(d,x,index*2,start,c)
update(d,x,index*2+1,c+1,last)
init(1,1,n)
for i in range(m+k):
a,b,c = map(int,sys.stdin.readline().strip().split())
if a == 1:
d = c - lst[b-1]
lst[b-1] = c
update(d,b,1,1,n)
else:
if b > c:
b,c = c,b
print(find(1,b,c,1,n))
재귀함수를 이용하여 start,last를 이용 start와 last 사이의 중간값 c를 구한 후
init(index,start,last) = init(index*2,start,c) + init(index*2 + 1,c+1,last)와 같은 식으로 재귀적으로 구현하면 된다.
init 함수와 find 함수를 조금 수정하면 구간의 합 뿐 아니라 구간의 최대값,최솟값, 곱 등도 구할 수 있다.
'백준 플레를 향해서' 카테고리의 다른 글
플레찍었으니 정리해보는 알고리즘 노트 6 - LIS(최장 증가 부분 수열) (0) | 2023.02.09 |
---|---|
플레찍었으니 정리해보는 알고리즘 노트 - 5 유니온파인드, 최소 신장 트리, 위상정렬 (1) | 2023.02.08 |
플레찍었으니 정리해보는 알고리즘 노트 3- GCD, 유클리드 호제법,오일러 피 함수 (0) | 2023.02.06 |
플레찍었으니 정리해보는 알고리즘 노트 2 - 중간에서 만나기, 투 포인터 (0) | 2023.02.06 |
플레찍었으니 정리해보는 알고리즘 노트 1 - 이진탐색 (0) | 2023.02.05 |