Submission #5916231


Source Code Expand

class Heap
  def initialize(n)
    @nodes = Array.new(n)
    @index = Hash.new
    @size = 0
  end

  def push(current_value)
    # 存在する値ならpushしないでreturn (入力を信じるのであれば、必要無い確認)
    return if @index[current_value]

    # 今から値を入れるのは、@size番目
    # 0番目...@size-1までの@size個の要素が元々あるから。
    current_index = @size
    @size += 1

    # 末端に要素を追加した時、その値が小さければ、どんどん親ノードへ上がっていく。
    while current_index > 0 do
      # 親ノードのindexは (i-1) >> 1 で計算できる
      # 親より自分が大きいなら、入れ替え不要でbreak
      parent_index = (current_index - 1)>>1
      parent_value = @nodes[parent_index]
      break if parent_value <= current_value

      # 親より自分が小さいので、入れ替え操作を行う。
      # 次のloopのために、current_indexを入れ替えた親のindexに直す
      @index[parent_value] = current_index
      @nodes[current_index] = parent_value
      current_index = parent_index
    end
    @index[current_value] = current_index
    @nodes[current_index] = current_value
  end

  def delete(delete_target_value)
    # 存在しない値ならdeleteできないのでreturn (入力を信じるのであれば、必要無い確認)
    return unless @index[delete_target_value]

    # 1.削除するのでsizeが減る
    # 2.末端は他のnodeと入れ替わるので、末端を削除する
    # 3.削除されるnodeのindexも削除する
    @size -= 1
    current_node_value = @nodes[@size]
    @nodes[@size] = nil
    current_node_index = @index.delete(delete_target_value) # delteの返り値は削除した値

    # 削除したのがそもそも末端だったら、終了。
    return if current_node_index == @size

    # 削除したのが末端じゃないなら、末端にある値を削除した場所に持ってくる
    @nodes[current_node_index] = current_node_value
    @index[current_node_value] = current_node_index

    # 大小関係が正されるように、要素を入れ替える

    # delete_target = d, last_node = l
    # d > l のとき
    # d_child > d > l で子は問題ないけど
    # d_parent < l < d, l < d_parent < d のどっちかわからなくて、後者だと問題なのでチェックする
    # この問題が解決するまで、親方向にチェック & 入れ替えを続ける
    if delete_target_value > current_node_value
      parent_node_index = (current_node_index - 1) >> 1
      while @nodes[parent_node_index]&.> @nodes[current_node_index]
        change(parent_node_index, current_node_index)
        current_node_index = parent_node_index
        current_node_value = @nodes[current_node_index]
        parent_node_index = (current_node_index - 1) >> 1
      end

    # d < l のとき
    # d_parent < d < d で親は問題ないけど
    # d_child > l > d, l > d_child > d のどっちかわからなくて、後者だと問題なのでチェックする
    # この時、(子1,子2,親) の内最小の値を新しい親にする事。
    # この問題が解決するまで、子方向にチェック & 入れ替えを続ける
    else
      while
        # 子ノードのindexを取得、小さい方(左)のindexがsize以上だったら、そこに要素は無いはずなのでbreak
        child_node_index_r = (current_node_index << 1) + 2
        child_node_index_l = child_node_index_r - 1
        break unless child_node_index_l < @size

        # 子ノードの内小さい方の値と、current_nodeを入れ替えるので、計算。
        # 右はnilの可能性があるので、右側のvalueからsafe navigation operatorを使う
        # 今のノードの値が、小さい方の子の値よりも小さかったそこでストップ
        child_node_value_l = @nodes[child_node_index_l]
        child_node_value_r = @nodes[child_node_index_r]
        if child_node_value_r&.<child_node_value_l
          min_child_value = child_node_value_r
          min_child_index = child_node_index_r
        else
          min_child_value = child_node_value_l
          min_child_index = child_node_index_l
        end
        break if min_child_value > current_node_value

        # 入れ替えた後、現在のindexを入れ替え先のindexにして、次のloopへ行く
        change(current_node_index, min_child_index)
        current_node_index = min_child_index
      end
    end
  end

  def top
    @size == 0 ? -1 : @nodes[0]
  end

  # デバッグ用
  def check_valid
    queue = [0]
    while queue.size > 0
      i = queue.shift
      child_1 = (i + 1) << 1
      child_2 = child_1 - 1
      if child_2 < @size
        if child_1 < @size
          queue << child_1
          raise if @nodes[child_1] < @nodes[i]
        end
        queue << child_2
        raise if @nodes[child_2] < @nodes[i]
      end
    end
  end

  private

  def change(index_i, index_j)
    @nodes[index_i], @nodes[index_j] = @nodes[index_j], @nodes[index_i]
    @index[@nodes[index_i]] = index_i
    @index[@nodes[index_j]] = index_j
  end
end

nn, qq = gets.split.map(&:to_i)
events = []
temp = []
1.step(nn, 1) do |_i|
  temp = gets.split.map(&:to_i)
  next if temp[1] - temp[2] <= 0
  x = temp[0] - temp[2]
  x = x > 0 ? x : 0

  events.push([temp[1] - temp[2], 1, temp[2]])
  events.push([temp[0] - temp[2], 0, temp[2]])
end
1.step(qq, 1) do |i|
  events.push([gets.to_i, 2, i])
end
events.sort_by!(&:first)

ss = Heap.new(nn)
ans = []

events.each do |event|
  if event[1] == 0
    ss.push(event[2])
  elsif event[1] == 1
    ss.delete(event[2])
  else
    ans[event[2]] = ss.top
  end
end

puts ans[1..-1]

Submission Info

Submission Time
Task E - Roadwork
User k_karen
Language Ruby (2.3.3)
Score 500
Code Size 5931 Byte
Status AC
Exec Time 1795 ms
Memory 68984 KiB

Judge Result

Set Name All Sample
Score / Max Score 500 / 500 0 / 0
Status
AC × 15
AC × 1
Set Name Test Cases
All killer_01, killer_02, killer_03, killer_04, random_dense, random_max, random_small_01, random_small_02, random_small_03, random_small_04, random_small_05, random_small_06, random_small_07, random_small_08, sample_01
Sample sample_01
Case Name Status Exec Time Memory
killer_01 AC 1541 ms 68984 KiB
killer_02 AC 1537 ms 68856 KiB
killer_03 AC 1554 ms 68984 KiB
killer_04 AC 737 ms 33400 KiB
random_dense AC 1795 ms 68216 KiB
random_max AC 1165 ms 43940 KiB
random_small_01 AC 13 ms 2044 KiB
random_small_02 AC 11 ms 1916 KiB
random_small_03 AC 11 ms 1916 KiB
random_small_04 AC 11 ms 1916 KiB
random_small_05 AC 12 ms 2040 KiB
random_small_06 AC 13 ms 2044 KiB
random_small_07 AC 13 ms 2044 KiB
random_small_08 AC 11 ms 1916 KiB
sample_01 AC 7 ms 1788 KiB