LoginSignup
0
0

More than 3 years have passed since last update.

ac-library-rb で解く AtCoder ABC 137 D

Last updated at Posted at 2021-05-26

はじめに

AtCoder Problems の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

今回のお題

AtCoder Beginner Contest D - Summer Vacation
Difficulty:1313

今回のテーマ、優先度付きキュー

ac-library-rb は、AtCoder Library (ACL)のRuby版です。

その ac-library-rb がなんとGem化されています。
ac-library-rb (rubygems)
AtCoderにインストールされる日が待ち遠しいですね。

優先度付きキュー

ruby.rb
# Priority Queue
# Reference: https://github.com/python/cpython/blob/master/Lib/heapq.py
class PriorityQueue
  # By default, the priority queue returns the maximum element first.
  # If a block is given, the priority between the elements is determined with it.
  # For example, the following block is given, the priority queue returns the minimum element first.
  # `PriorityQueue.new { |x, y| x < y }`
  #
  # A heap is an array for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for all k, counting elements from 0.
  def initialize(array = [], &comp)
    @heap = array
    @comp = comp || proc { |x, y| x > y }
    heapify
  end

  attr_reader :heap

  # Push new element to the heap.
  def push(item)
    shift_down(0, @heap.push(item).size - 1)
  end

  alias << push
  alias append push

  # Pop the element with the highest priority.
  def pop
    latest = @heap.pop
    return latest if empty?

    ret_item = heap[0]
    heap[0] = latest
    shift_up(0)
    ret_item
  end

  # Get the element with the highest priority.
  def get
    @heap[0]
  end

  alias top get

  # Returns true if the heap is empty.
  def empty?
    @heap.empty?
  end

  private

  def heapify
    (@heap.size / 2 - 1).downto(0) { |i| shift_up(i) }
  end

  def shift_up(pos)
    end_pos = @heap.size
    start_pos = pos
    new_item = @heap[pos]
    left_child_pos = 2 * pos + 1

    while left_child_pos < end_pos
      right_child_pos = left_child_pos + 1
      if right_child_pos < end_pos && @comp.call(@heap[right_child_pos], @heap[left_child_pos])
        left_child_pos = right_child_pos
      end
      # Move the higher priority child up.
      @heap[pos] = @heap[left_child_pos]
      pos = left_child_pos
      left_child_pos = 2 * pos + 1
    end
    @heap[pos] = new_item
    shift_down(start_pos, pos)
  end

  def shift_down(star_pos, pos)
    new_item = @heap[pos]
    while pos > star_pos
      parent_pos = (pos - 1) >> 1
      parent = @heap[parent_pos]
      break if @comp.call(parent, new_item)

      @heap[pos] = parent
      pos = parent_pos
    end
    @heap[pos] = new_item
  end
end

n, m = gets.split.map(&:to_i)
ab = Array.new(100000 + 1){ [] }
n.times do
  a, b = gets.split.map(&:to_i)
  ab[a] << b
end
ans = 0
pq = PriorityQueue.new
1.upto(m) do |i|
  next if ab[i].nil?
  ab[i].each do |e|
    pq << e
  end
  ans += pq.pop if !pq.empty?
end
puts ans

今はインストールされていないのでclass部分を追記する必要があります。

upto.rb
1.upto(m) do |i|

最終日に近い日から貪欲に選択します。

まとめ

  • 優先度付きキュー(Priority Queue) を解いた
  • ACL に詳しくなった
  • Ruby に詳しくなった
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0