๋ฐฑ์ค€ - ๊ฐ•์˜์‹ค ๋ฐฐ์ •(Swift)

2022. 10. 28. 09:48ใ†Algorithm

๋ฐฑ์ค€ - ๊ฐ•์˜์‹ค ๋ฐฐ์ •(Swift)

 

 

 ๋ฌธ์ œ ์„ค๋ช…

 

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

 

11000๋ฒˆ: ๊ฐ•์˜์‹ค ๋ฐฐ์ •

์ฒซ ๋ฒˆ์งธ ์ค„์— N์ด ์ฃผ์–ด์ง„๋‹ค. (1 ≤ N ≤ 200,000) ์ดํ›„ N๊ฐœ์˜ ์ค„์— Si, Ti๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. (0 ≤ Si < Ti ≤ 109)

www.acmicpc.net

 

 

 

 ๋‚˜์˜ ํ’€์ด

 

์šฐ์„ ์ˆœ์œ„ ํ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•œ ๋ฌธ์ œํ’€์ด์ด๋‹ค.

 

์ž…๋ ฅ๊ฐ’์ด 100,000์ด ๋„˜์–ด๊ฐˆ ๋•Œ๋Š” ์šฐ์„ ์ˆœ์œ„ํ๊ฐ™์€ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ ์ ์€ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋– ์˜ฌ๋ ค์•ผํ•œ๋‹ค.

 

์ด ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š”๋ฐ ์–ด๋ ค์› ๋˜ ์ ์€ ๋‘๊ฐ€์ง€์ด๋‹ค.

1. ๊ฐ•์˜๋ฅผ ์‹œ์ž‘์‹œ๊ฐ„์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ.

2. ์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ.

 

์ฒซ ๋ฒˆ์งธ๋ฅผ ์ƒ๊ฐํ•˜๊ธฐ์ „์— ์ฒ˜์Œ์— ๊ฐ•์˜๋ฅผ ๋๋‚œ์‹œ๊ฐ„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ์„ ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ตœ์†Œ์˜ ๊ฐ•์˜์‹ค์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ œ์ผ ๋นจ๋ฆฌ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋จผ์ € ์‹œ์ž‘ํ•˜๋Š” ๊ฒŒ ๊ฐ€์žฅ ๊ทธ๋ฆฌ๋””ํ•˜๋‹ค.

 

๋‘ ๋ฒˆ์งธ๋Š” ์‚ฌ๋žŒ๋“ค์ด ๊ตฌํ˜„ํ•ด๋†“์€ ์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์ด์šฉํ–ˆ๋Š”๋ฐ peek()๋ฉ”์„œ๋“œ๋‚˜ remove(at:)๋“ฑ ์‚ฌ์šฉ๋ฒ•์„ ๋ชฐ๋ผ์„œ ํ•ด๋ฉจ์—ˆ๋‹ค. 

 

์ด ๋‘ ๊ฐ€์ง€๋ฅผ ํ•ด๊ฒฐํ•˜๋‹ˆ ๋ฌธ์ œ๊ฐ€ ํ’€๋ ธ๋‹ค.

 

public struct Heap<T> {
    
    private var nodes = [T]()
    
    private var orderCriteria: (T, T) -> Bool
    
    public init(sort: @escaping (T, T) -> Bool) {
        // ์ตœ๋Œ€ ํž™์ธ์ง€ ์ตœ์†Œ ํž™์ธ์ง€ ๊ธฐ์ค€์„ ์žก๋Š”๋‹ค.
        self.orderCriteria = sort
    }
    
    public init(array: [T], sort: @escaping (T, T) -> Bool) {
        self.orderCriteria = sort
        configureHeap(from: array)
    }
    
    public var count: Int {
        return nodes.count
    }
    
    public func peek() -> T? {
        return nodes.first
    }
    
    public mutating func insert(_ value: T) {
        nodes.append(value)
        shiftUp(nodes.count - 1)
    }
    
    public mutating func remove() -> T? {
        guard !nodes.isEmpty else { return nil }
        
        if nodes.count == 1 {
            return nodes.removeLast()
        } else {
            let value = nodes[0]
            nodes[0] = nodes.removeLast()
            shiftDown(0)
            return value
        }
    }
    
    public mutating func remove(at index: Int) -> T? {
        guard index < nodes.count else { return nil }
        
        let lastIndex = nodes.count-1
        if index != lastIndex {
            nodes.swapAt(index, lastIndex)
            shiftDown(from: index, until: lastIndex)
            shiftUp(index)
        }
        
        return nodes.removeLast()
    }
    
    // ๋ณ€์ˆ˜๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— mutating ์„ ์‚ฌ์šฉํ•œ๋‹ค.
    private mutating func configureHeap(from array: [T]) {
        nodes = array
        
        /**
         * ํž™ ํŠธ๋ฆฌ์—์„œ n/2 - 1 ์€ ํ•˜๋‚˜ ์œ„ ์ธต์œ„๊ฐ€ ๋œ๋‹ค.
         * shiftDown์„ ํ•˜๋ฉด์„œ ์ž๋ฆฌ๋ฅผ ์žก์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—
         * ๋งˆ์ง€๋ง‰ leaf ๋…ธ๋“œ๋“ค์€ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
         */
        for i in stride(from: nodes.count/2 - 1, through: 0, by: -1) {
            shiftDown(i)
        }
    }
    
    private func parentIndex(ofIndex i: Int) -> Int {
        return (i - 1) / 2
    }
    
    private func leftChildIndex(ofIndex i: Int) -> Int {
        return 2*i + 1
    }
    
    private func rightChildIndex(ofIndex i: Int) -> Int {
        return 2*i + 2
    }
    
    /**
     * shiftUp์€ ์ž์‹ ๊ณผ ๋ถ€๋ชจ๋ฅผ ๋น„๊ตํ•ด ๋ฐ”๊ฟ”์ค€๋‹ค.
     */
    private mutating func shiftUp(_ index: Int) {
        var childIndex = index
        let child = nodes[childIndex] // ์ฒ˜์Œ์— ๋…ธ๋“œ๋ฅผ ์ €์žฅํ•ด๋‘๊ณ  ์ธ๋ฑ์Šค๋ฅผ ๊ตฌํ•œ ํ›„ ๋ฐ”๊ฟ”์ค€๋‹ค.
        var parentIndex = self.parentIndex(ofIndex: index)
        
        while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) {
            nodes[childIndex] = nodes[parentIndex]
            childIndex = parentIndex
            parentIndex = self.parentIndex(ofIndex: childIndex)
        }
        
        nodes[childIndex] = child
    }
    
    /**
     * shiftDown์€ left, right ์ž์‹ ์ค‘ ์ ํ•ฉํ•œ ๋…€์„์ด ์žˆ์œผ๋ฉด ๋ฐ”๊พธ๋ฉด์„œ ๋ฐ”๋‹ฅ๊นŒ์ง€ ๋‚ด๋ ค๊ฐ„๋‹ค.
     */
    private mutating func shiftDown(from index: Int, until endIndex: Int) {
        let leftChildIndex = self.leftChildIndex(ofIndex: index)
        let rightChildIndex = leftChildIndex + 1
        
        var first = index
        if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) {
            first = leftChildIndex
        }
        if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) {
            first = rightChildIndex
        }
        if first == index { return }
        
        nodes.swapAt(index, first)
        shiftDown(from: first, until: endIndex)
    }
    
    private mutating func shiftDown(_ index: Int) {
        shiftDown(from: index, until: nodes.count)
    }
    
}

var lectures = [(Int, Int)]()

for _ in 0..<Int(readLine()!)! {
    let input = readLine()!.split(separator: " ").map { Int(String($0))! }
    lectures.append((input[0], input[1]))
}

lectures.sort(by: <)
var heap = Heap<Int>(sort: <)
heap.insert(lectures[0].1)

for i in 1..<lectures.count {
    if lectures[i].0 < heap.peek()! {
        heap.insert(lectures[i].1)
    } else {
        heap.remove(at: 0)
        heap.insert(lectures[i].1)
    }
}

print(heap.count)