문제 소개
풀이 과정
아주아주 단순하게 문제에 접근하면 아래와 같이 할 수 있을 것이다. 단순히 table을 만든 후 아래처럼 입력값에 따라서 성실하게(?) 답변을 구현한다. 물론 이렇게 풀게된다면 M 100,000이고, N 1,024일때 최악의 경우 1,024 x 1,024 x 100,000번 연산을 해야하기 때문에 시간초과다. ☠️
import Foundation
let nm = readLine()!.components(separatedBy: " ").map { Int($0)! }
let (n, m) = (nm[0], nm[1])
var table = [[Int]]()
for _ in 0..<n {
table.append(readLine()!.components(separatedBy: " ").map { Int($0)! })
}
for _ in 0..<m {
let input = readLine()!.components(separatedBy: " ").map { Int($0)! }
let (x1, y1, x2, y2) = (input[0]-1, input[1]-1, input[2]-1, input[3]-1)
var result = 0
for i in x1...x2 {
for j in y1...y2 {
result += table[i][j]
}
}
print(result)
}
어떻게 이문제를 해결 할 수 있을까? 아래와 같은 개념을 사용하면 된다. dp로 [1][1]부터 [i][j]의 누적합을 구하게 된다면 아래와 같은 연산으로 선택한 영역의 합을 구할 수 있다.
..... ooooo oo... ooooo oo...
..ooo = ooooo - oo... - ..... + .....
..ooo ooooo oo... ..... .....
또한 입력값이 10만이 넘기 때문에 FileIO라이브러리를 활용했다...
import Foundation
final class FileIO {
private let buffer:[UInt8]
private var index: Int = 0
init(fileHandle: FileHandle = FileHandle.standardInput) {
buffer = Array(try! fileHandle.readToEnd()!)+[UInt8(0)]
}
@inline(__always) private func read() -> UInt8 {
defer { index += 1 }
return buffer[index]
}
@inline(__always) func readInt() -> Int {
var sum = 0
var now = read()
var isPositive = true
while now == 10
|| now == 32 { now = read() }
if now == 45 { isPositive.toggle(); now = read() }
while now >= 48, now <= 57 {
sum = sum * 10 + Int(now-48)
now = read()
}
return sum * (isPositive ? 1:-1)
}
@inline(__always) func readString() -> String {
var now = read()
while now == 10 || now == 32 { now = read() }
let beginIndex = index-1
while now != 10,
now != 32,
now != 0 { now = read() }
return String(bytes: Array(buffer[beginIndex..<(index-1)]), encoding: .ascii)!
}
@inline(__always) func readByteSequenceWithoutSpaceAndLineFeed() -> [UInt8] {
var now = read()
while now == 10 || now == 32 { now = read() }
let beginIndex = index-1
while now != 10,
now != 32,
now != 0 { now = read() }
return Array(buffer[beginIndex..<(index-1)])
}
}
let fIO = FileIO()
let n = fIO.readInt()
let m = fIO.readInt()
var dp = Array(repeating: Array(repeating: 0, count: n+2), count: n+2)
// 값 입력
for i in 1...n {
for j in 1...n {
let input = fIO.readInt()
dp[i][j] = input
}
}
// 누적합 계산
for i in 1...n {
for j in 1...n {
dp[i][j] += dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]
}
}
// 계산된 dp활용
for _ in 0..<m {
let x1 = fIO.readInt()
let y1 = fIO.readInt()
let x2 = fIO.readInt()
let y2 = fIO.readInt()
print(dp[x2][y2] - dp[x2][y1-1] - dp[x1-1][y2] + dp[x1-1][y1-1])
}
'→ Problems' 카테고리의 다른 글
[Algorithm] 백준 - 13560번 축구 게임 (Swift) (0) | 2024.08.12 |
---|---|
[Algorithm] 백준 - 1074번 Z (Swift) (0) | 2024.07.29 |
[Algorithm] 백준 - 2098번 외판원 순회 (Swift) (0) | 2024.07.28 |
[Algorithm] 백준 - 11689번 GCD(n, k) = 1 (0) | 2024.07.09 |
[Algorithm] 백준 - 16565번 포커 (Swift) (0) | 2024.07.08 |