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

  def push(x)
    i = @size
    @size += 1
    while i > 0 do
      #親ノードのindex
      t = (i-1)>>1
      # 親より自分が大きいなら、入れ替え不要
      break if @nodes[t] <= x
      # 親より自分が小さい時、入れ替え操作を行う
      @index[@nodes[t]] = i
      @nodes[i] = @nodes[t]
      i = t
    end
    @index[x] = i
    @nodes[i] = x
  end

  def delete(x)
    # 削除したい値のあるindexへ、最新nodeの値を入れる
    current_node_value = @nodes[@size - 1]
    return unless current_node_index = @index.delete(x)
    @size -= 1
    @nodes[current_node_index] = current_node_value
    @index[current_node_value] = current_node_index

    # 大小関係が正されるように、要素を入れ替える
    if x > current_node_value
      # 末端のほうが削除する値よりも小さかった場合は、親ノードへ入れ替えを確認していく
      parent_node_index = (current_node_index - 1) >> 1
      while @nodes[parent_node_index] < @nodes[current_node_index] do
        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
    else
      # 末端のほうが大きかった場合は、子ノードへ入れ替えを確認していく
      # 末端のほうが削除する値よりも小さかった場合は、親ノードへ入れ替えを確認していく
      child_node_index_l = (current_node_index + 1) << 1
      child_node_index_r = child_node_index_l - 1
      child_node_value_l = @nodes[child_node_index_l]
      child_node_value_r = @nodes[child_node_index_r]
      if child_node_value_l&.>(child_node_value_r)
        min_child_info = [child_node_value_r , child_node_index_r]
      else
        min_child_info = [child_node_value_l , child_node_index_l]
      end
      while (min_child_info[0]&.<(current_node_value)) do
        change(current_node_index, min_child_info[1])
        current_node_index = min_child_info[1]
        current_node_value = min_child_info[0]
        child_node_index_l = (current_node_index + 1) << 1
        child_node_index_r = child_node_index_l - 1
        break if child_node_index_r >= @size
        child_node_value_l = @nodes[child_node_index_l]
        child_node_value_r = @nodes[child_node_index_r]
        min_child_info = (child_node_value_l&.>(child_node_value_r)) ? [child_node_value_r , child_node_index_r] : [child_node_value_l , child_node_index_l]
      end
    end
  end

  def top
    @size == 0 ? -1 : @nodes[0]
  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

