import Foundation
let input = readLine()!.split(separator: " ").map { Int(String($0))! }
let (N, M, K) = (input[0], input[1], input[2])
let MOD = 1000000007
// 세그먼트 트리 초기화
let height = ceil(log2(Double(N)))
let size = Int(pow(2.0, height + 1))
var tree = Array(repeating: 1, count: size + 1)
setTree()
// 질의 수행
for _ in 0..<M+K {
let input = readLine()!.split(separator: " ").map { Int(String($0))! }
if input[0] == 1 {
updateTree(input[1], input[2])
} else {
print(getMul(input[1], input[2]))
}
}
func setTree() {
// 원본 데이터 저장
for i in 0..<N {
let index = Int(pow(2.0, height)) + i
let input = Int(readLine()!)!
tree[index] = input
}
// 부분 곱 저장
var index = size
while index != 1 {
tree[index / 2] = tree[index / 2] * tree[index] % MOD
index -= 1
}
}
func updateTree(_ target: Int, _ value: Int) {
var index = target + Int(pow(2.0, height)) - 1
tree[index] = value
while index > 1 {
index = index / 2
tree[index] = tree[index * 2] % MOD * tree[index * 2 + 1] % MOD
}
}
func getMul(_ a: Int, _ b: Int) -> Int {
var start = a + Int(pow(2.0, height)) - 1
var end = b + Int(pow(2.0, height)) - 1
var result = 1
while start <= end {
if start % 2 == 1 { result = result * tree[start] % MOD }
if end % 2 == 0 { result = result * tree[end] % MOD }
start = (start + 1) / 2
end = (end - 1) / 2
}
return result
}
세그먼트 트리를 사용해서 구간 곱을 구하는 문제이다.
이 문제에서 신경써야 할 부분은 크게 두 가지이다.
원래 모듈러 연산을 포함하는 부분에서 tree[index / 2] *= tree[index] % MOD
이런 식으로 *=
연산자를 사용했더니 런타임 에러가 발생했다. 이 연산자를 사용하면 계산 순서가 의도했던 것과 달라져서 오버플로우가 발생하는 것이 원인인 것 같다.