https://www.acmicpc.net/problem/2357

 

2357번: 최솟값과 최댓값

N(1 ≤ N ≤ 100,000)개의 정수들이 있을 때, a번째 정수부터 b번째 정수까지 중에서 제일 작은 정수, 또는 제일 큰 정수를 찾는 것은 어려운 일이 아니다. 하지만 이와 같은 a, b의 쌍이 M(1 ≤ M ≤ 100

www.acmicpc.net

세그먼트 트리 문제다.

 

풀이

각 노드에 (Int, Int) 자료형을 통해 최솟값과 최댓값을 담는 세그먼트 트리를 생성하여, 각 구간별 최솟값과 최댓값이 담기는 세그먼트 트리를 생성하여 조건에 맞게 출력하면 된다.

 

[1,2,3,4,5] 배열을 기준으로 만든 세그먼트 트리다. 리프노드에는 동일한 값을 넣었다. 

 

트리를 읽어야 할 때는 구간에 해당하는 노드를 탐색, 각각의 최댓값과 최솟값을 비교하여 반환하면 된다.

해당 그림은 1 ~ 4번 인덱스 구간의 최솟값, 최댓값을 읽어올 때 참고하게 될 노드다.

범위 밖의 노드라면 입력 범위의 최댓값과 최솟값을 바꾸어 출력하게 하였다. ((1,000,000,000, 1) 리턴)

 

정답 코드

import Foundation
//by rhyno
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 arr = [Int]()
var tree = Array(repeating: (1000000001,0), count: N*4)
for _ in 0..<N{
arr.append(fio.readInt())
}
func make_tree(from:Int, to:Int, idx:Int) -> (Int,Int){
if from == to{
tree[idx] = (arr[from],arr[from])
return tree[idx]
}
let mid = (from+to)/2
let l = make_tree(from: from, to: mid, idx: idx*2)
let r = make_tree(from: mid+1, to: to, idx: idx*2+1)
tree[idx].0 = min(l.0, r.0)
tree[idx].1 = max(l.1, r.1)
return tree[idx]
}
func read_tree(from:Int, to:Int, idx:Int, head:Int, tail:Int) -> (Int,Int){
if to < head || tail < from{
return (1000000001,0)
}
if head <= from && to <= tail{
return tree[idx]
}
let mid = (from+to)/2
let l = read_tree(from: from, to: mid, idx: idx*2, head: head, tail: tail)
let r = read_tree(from: mid+1, to: to, idx: idx*2+1, head: head, tail: tail)
return (min(l.0, r.0),max(l.1, r.1))
}
make_tree(from: 0, to: N-1, idx: 1)
for _ in 0..<M{
let start = fio.readInt()-1
let end = fio.readInt()-1
let res = read_tree(from: 0, to: N-1, idx: 1, head: start, tail: end)
print(res.0,res.1)
}
view raw 2357.swift hosted with ❤ by GitHub

'Problem Solving > BOJ' 카테고리의 다른 글

[14428] 수열과 쿼리 16  (0) 2023.02.17
[11505] 구간 곱 구하기  (0) 2023.02.16
[2042] 구간 합 구하기  (0) 2023.02.15
[2533] 사회망 서비스(SNS)  (0) 2023.02.13
[11054] 가장 긴 바이토닉 부분 수열  (0) 2023.02.12

+ Recent posts