https://level.goorm.io/exam/51351/%EC%9E%A1%EC%B4%88-%EC%A0%9C%EA%B1%B0/quiz/1
구름LEVEL
코딩테스트에서 가장 높은 비중을 차지하는 알고리즘 문제를 제작하고 풀이할 수 있는 온라인 저지 서비스입니다. 기업에서 선호하는 C, C++, 파이썬(Python), 자바(Java), 자바스크립트(Javascript) 이외에 여러 가지 프로그래밍 언어로 풀이할 수 있습니다.
level.goorm.io


Segment Tree라는 개념을 처음 알게 된 문제.
Segment Tree 개념을 쉽게 설명한 포스트는 아래와 같다.
세그먼트 트리(Segment Tree)
세그먼트 트리(Segment Tree)는 요청하는 쿼리에 대해 방식이 달라질 수 있으나, 모든 쿼리를 다룰 수 없기에 구간 합에 대한 세그먼트 트리를 정리해 두었습니다. 내용이 길지만 그만큼 자세히 설명하려 노력하였..
www.crocus.co.kr
Python 코드는 아래 포스트를 참고해서 만들었다.
https://upcount.tistory.com/12
백준 2042번 구간 합 (Python)
세그먼트 트리 (Segment Tree) 배열 A가 있고 다음과 같은 두 연산을 수행해야하는 문제를 생각해보자. 1. 구간 l, r이 주어졌을 때, A[l] + ... A[r] 구해서 출력하기 2. i번째 수를 V로 바꾸기. A[i] = v 수행해..
upcount.tistory.com
import sys | |
import math | |
n, q = map(int, sys.stdin.readline().split()) | |
# 잡초 | |
maps = list(map(int, sys.stdin.readline().split())) | |
# 트리를 위한 배열 크기 | |
# N이 2 * 10**5. log_2(N) = 1 + 5*log_2(2*5) | |
# print(5 * math.log(10, 2)) = 16.610 정도 된다. 즉 배열 크기는 17은 넘어야 한다 | |
# print(2**17) = 131072, print(2**18) = 262144 | |
# 트리니까 2**18 값에 * 2를 하면 모든 연산값을 담을 수 있는 배열을 만들 수 있다. | |
Tree = [0 for _ in range(2**19)] | |
# 트리 생성하기 | |
def init(n, start, end): | |
if start == end: | |
Tree[n] = maps[start] | |
return Tree[n] | |
# 트리의 좌측 / 우측의 값을 더한 값이 해당 트리 node의 값 | |
Tree[n] = init(n*2, start, (start+end)//2) + init(n*2 + 1, ((start+end) // 2) + 1, end) | |
return Tree[n] | |
# 부분합 구하기 | |
# 구하려는 범위는 left - right. | |
def subSum(node, start, end, left, right): | |
# 탐색범위인 start, end가 구하려는 범위 left-right 어디에도 포함이 안 되면 더 이상 구할 필요가 없다 | |
if left > end or right < start: | |
return 0 | |
# 구하려는 범위 start, end가 탐색범위 left, right에 완전히 포함되면, 더 이상 내려갈 필요가 없다 | |
if left <= start and end <= right: | |
return Tree[node] | |
# 왼쪽 노드 / 오른쪽 노드로 나눠 탐색한 값을 반환한다. | |
return subSum(node * 2, start, (start+end)//2, left, right) + subSum(node*2 + 1, ((start+end)//2) + 1, end, left, right) | |
def update(node, start, end, index, value): | |
# 바꾸는 숫자의 index값이 탐색 범위 start, end에 포함되지 않을 경우 - 연산할 필요 없다 | |
if index < start or index > end: | |
return | |
Tree[node] += value | |
# 리프노드에 도달할 때까지, 노드값을 계속 바꾸면서 내려간다 | |
if start != end: | |
update(node*2, start, (start+end)//2, index, value) | |
update(node*2 + 1, (start+end)//2 + 1, end, index, value) | |
# root node의 index = 1 | |
init(1, 0, len(maps)-1) | |
for _ in range(q): | |
q, a, b = map(int, sys.stdin.readline().split()) | |
# index 조절 | |
a -= 1 | |
if q == 1: | |
b -= 1 | |
print(subSum(1, 0, len(maps)-1, a,b)) | |
elif q == 2: | |
update(1, 0, len(maps)-1, a, b) | |
elif q == 3: | |
update(1, 0, len(maps)-1, a, -b) |
'프로그래밍 > 코딩테스트 문제풀이' 카테고리의 다른 글
[Python] 프로그래머스. 타일 장식물 (Level 3) (0) | 2020.05.06 |
---|---|
[Python] 구름. 그룹 지정 (0) | 2020.05.04 |
[Python] 구름. 개구리 2 (0) | 2020.04.29 |
[Python] 구름. 소수 고리 (1) | 2020.04.28 |
[Python] 구름. 근묵자흑 (0) | 2020.04.24 |