14003 swift - 가장 긴 증가하는 부분 수열 5
2024. 10. 18. 07:42ㆍ🐣/BOJ
LIS의 플래티넘 버전. 수열 문제들을 풀다보면 어렵지 않게 풀 수 있다.
dp로 풀면 O^2이므로 이진탐색을 이용하여 현재 수열들을 교체해가며 뽑아주고, 마지막 indices의 요소를 사용하여 parent를 역추적하여 뽑아내주면 된다.
import Foundation
var arr: [Int] = []
var sequence: [Int] = []
var indices: [Int] = []
var parent: [Int] = []
var N: Int = 0
func binarySearch(_ num: Int) -> Int {
var low = 0, high = sequence.count - 1
var mid = 0
while low <= high {
mid = (low + high) / 2
let here_num = sequence[mid]
if here_num >= num {
high = mid - 1
} else {
low = mid + 1
}
}
return low
}
func findLIS() {
sequence.append(arr[0])
indices.append(0)
parent.append(-1)
for i in 1..<N {
if sequence.last! < arr[i] {
parent.append(indices.last!)
sequence.append(arr[i])
indices.append(i)
} else {
let pos = binarySearch(arr[i])
sequence[pos] = arr[i]
indices[pos] = i
parent.append(pos > 0 ? indices[pos - 1] : -1)
}
}
}
func reconstructLIS() -> [Int] {
var lis: [Int] = []
var currentIndex = indices.last!
while currentIndex != -1 {
lis.append(arr[currentIndex])
currentIndex = parent[currentIndex]
}
return lis.reversed()
}
N = Int(readLine()!)!
arr = readLine()!.split(separator: " ").map { Int(String($0))! }
findLIS()
let lis = reconstructLIS()
print(lis.count)
print(lis.map{ String($0) }.joined(separator: " "))
'🐣 > BOJ' 카테고리의 다른 글
17069 c++ - 파이프 옮기기 2 (0) | 2024.10.22 |
---|---|
1644 c++ - 소수의 연속합 (0) | 2024.10.21 |
17088 c++ - 등차수열 변환 (0) | 2024.10.17 |
16235 c++ - 나무 재테크 (12) | 2024.10.08 |
1299 c++ - 전쟁-탈출편2 (0) | 2024.10.05 |