HTD
[Python] 백준 1395번: 스위치 본문
https://www.acmicpc.net/problem/1395
1395번: 스위치
첫 줄에는 스위치의 개수 N(2 ≤ N ≤ 100,000)과 처리할 일의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 M개의 줄에 대해 각 줄에 처리할 일에 대한 정보가 담겨진 세 개의 정수 O, Si, Ti가 입력된다. O
www.acmicpc.net
Segment Tree의 응용인 Lazy propagation의 응용 문제이다. Lazy propagation의 상세한 설명은 아래 링크에 담겨있다.
[Python] Lazy Propagation (백준 10999번: 구간 합 구하기 2)
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은 수의 변경이 일어나는 횟수이고,..
rccode.tistory.com
특정 범위에 특정 값을 더하는 것이 아니라, 스위치를 On/Off 하는 방식이므로 이에 대해서 변형을 해줘야한다. 가장 중요한 propagate 함수를 보자.
def propagate_segment_tree(index, start, end):
if lazy[index] != 0:
seg_tree[index] = (end - start + 1) - seg_tree[index]
if start != end:
lazy[index*2] ^= 1
lazy[index*2+1] ^= 1
lazy[index] = 0
lazy의 값은 0 또는 1이며, 1일 때 스위치를 반전시키는 식으로 설계한다. (end - start + 1)은 범위에서 모든 스위치를 켰을 때의 합이고, 여기서 현재 값을 빼주면 결과적으로 스위치를 반전시켰을 때의 값을 얻게 된다.
그리고 자식 노드의 lazy 값을 반전시킨다. 1을 넣어주는 것이 아니라 반전시켜주는 이유는 아래 케이스를 통해 알 수 있다.
3 3
0 1 3
0 1 3
1 1 2
그리고, update 함수에서도 위와 같이 해주면 된다.
아래는 소스 코드이다.
import sys
import math
input = sys.stdin.readline
def get_segment_tree_length():
if N & (N-1) == 0:
return 2*N
else:
return pow(2, math.ceil(math.log(N, 2)) + 1)
def update_segment_tree(index, start, end, left, right):
propagate_segment_tree(index, start, end)
# Out of range
if right < start or end < left:
return
# In range
if left <= start and end <= right:
seg_tree[index] = (end - start + 1) - seg_tree[index]
if start != end:
lazy[index*2] ^= 1
lazy[index*2+1] ^= 1
return
mid = (start + end)//2
update_segment_tree(index*2, start, mid, left, right)
update_segment_tree(index*2+1, mid+1, end, left, right)
seg_tree[index] = seg_tree[index*2] + seg_tree[index*2+1]
def query_segment_tree(index, start, end, left, right):
propagate_segment_tree(index, start, end)
# Out of range
if right < start or end < left:
return 0
# In range
if left <= start and end <= right:
return seg_tree[index]
mid = (start + end)//2
return query_segment_tree(index*2, start, mid, left, right) + query_segment_tree(index*2+1, mid+1, end, left, right)
def propagate_segment_tree(index, start, end):
if lazy[index] != 0:
seg_tree[index] = (end - start + 1) - seg_tree[index]
if start != end:
lazy[index*2] ^= 1
lazy[index*2+1] ^= 1
lazy[index] = 0
if __name__ == '__main__':
N, M = map(int, input().split())
length = get_segment_tree_length()
seg_tree = [0]*length
lazy = [0]*length
for _ in range(M):
o, s, t = map(int, input().split())
if o == 0:
update_segment_tree(1, 1, N, s, t)
else:
print(query_segment_tree(1, 1, N, s, t))
'Algorithm > 백준' 카테고리의 다른 글
[Python] 백준 1766번: 문제집 (0) | 2021.09.05 |
---|---|
[Python] 백준 1644번: 소수의 연속합 (0) | 2021.09.03 |
[Python] 백준 14725번: 개미굴 (0) | 2021.09.02 |
[Python] Lazy Propagation (백준 10999번: 구간 합 구하기 2) (0) | 2021.09.01 |
[C] 백준 2750번: 수 정렬하기 (0) | 2021.08.31 |