https://www.acmicpc.net/problem/10999
10999번: 구간 합 구하기 2
첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 횟수이고, K는 구간의 합을 구하는 횟수이다. 그리고 둘째 줄부터 N+1번째 줄
www.acmicpc.net
문제 접근
세그먼트 트리로 그냥 풀면 틀릴것같아서 좀 찾아봤다.
느리게 갱신되는 세그먼트 트리라는게 있어서 공부했더니 쉽게 풀렸다.
방법은 아래 링크에서 잘알려준다
https://book.acmicpc.net/ds/segment-tree-lazy-propagation
느리게 갱신되는 세그먼트 트리
소스 1void update_range(vector &tree, int node, int start, int end, int left, int right, long long diff) { if (left > end || right < start) { return; } if (start == end) { tree[node] += diff; return; } update_range(tree, node*2, start, (start+end)/2, lef
book.acmicpc.net
지금 값을 갱신해버리면 너무 시간소모가 크기때문에, 새로운 변수를 만들어두고 갱신할 값을 적어둔다.
누적합 부분만 갱신하면서 트리의 아래로 더 내려가지않고 버티는 느낌이다.
그리고 아래 노드에 접근해야하면 한번에 갱신한다.
매번 접근할때마다 새로만든 lazy라는 변수에 값이 0인지 체크해야한다.
코드
import sys
import math
input = sys.stdin.readline
"""
10999
세그먼트 트리로 만들면 되긴 한데
넓은 범위를 부분이 넓어도 시간초과가 안날까?
1000000개를 10000번 수정하고 시간제한2초. 시간초과
!느리게 갱신되는 세그먼트 트리! 사용 시 해결가능
"""
N, M, K = map(int,input().split())
node = 2**(math.ceil(math.log2(N)))
tree = [0 for i in range(node*2)]
lazy = [0 for i in range(node*2)]
for i in range(N):
tree[node+i] = int(input())
def init(index):
if index<node:
tree[index] = init(index*2) + init(index*2+1)
return tree[index]
def updateLazy(start, end, index):
if lazy[index]:
tree[index] += (end-start+1) * lazy[index]
if start!=end:
lazy[index*2] += lazy[index]
lazy[index*2+1] += lazy[index]
lazy[index] = 0
def updateRange(targetStart, targetEnd, start, end, index, val):
updateLazy(start, end, index)
if start > targetEnd or end < targetStart:
return
if targetStart <= start and end <= targetEnd:
tree[index] += (end-start+1) * val
if start != end:
lazy[index*2] += val
lazy[index*2+1] += val
return
mid = (start + end) // 2
updateRange(targetStart, targetEnd, start, mid, index*2, val)
updateRange(targetStart, targetEnd, mid + 1, end, index*2+1, val)
tree[index] = tree[index*2] + tree[index*2+1]
def printSum(targetStart, targetEnd, start, end, index):
updateLazy(start, end, index)
if start > targetEnd or end < targetStart:
return 0
if targetStart <= start and end <= targetEnd:
return tree[index]
mid = (start + end) // 2
return printSum(targetStart, targetEnd, start, mid, index*2) + printSum(targetStart, targetEnd, mid + 1, end, index*2+1)
init(1)
for i in range(M+K):
abc = list(map(int,input().split()))
if abc[0] == 1:
updateRange(abc[1], abc[2], 1, node, 1, abc[3])
else:
print(printSum(abc[1], abc[2], 1, node, 1))
'백준 > 문제풀이_python' 카테고리의 다른 글
18436 수열과 쿼리 37 python (0) | 2024.02.05 |
---|---|
2243 사탕상자 python (0) | 2024.02.04 |
2024 구간 합 구하기 python (0) | 2024.02.02 |
13537 수열과 쿼리 1 python (0) | 2024.02.01 |
14427 수열과 쿼리 15 (0) | 2024.01.31 |
댓글