num, time = gets.split.map(&:to_i)
time -= 1
foods = []
num.times { foods << gets.split.map(&:to_i) }
foods.sort!

# 許容重量ごとの価値の最大値を格納するdp（順次更新）
dp = Array.new(time + 1, 0)

ans = []

# 1個目からnum個目までの品物を、ナップサックに入れるべきか順番に確認する
1.upto(num) do |n|
  # n個目の時間をtmp_time、価値をtmp_valueとする
  tmp_time, tmp_value = foods[n - 1]
  # n個目を最後に食べたと仮定した時の総価値を保存
  ans << dp[time] + tmp_value
  # 許容時間がtimeからtmp_timeまでの場合を、順番に確認する
  # （許容時間がtmp_time未満の場合、ナップサックに入れることはできないため確認の必要なし）
  # なお、uptoを用いて逆向きに確認すると、ループ中に既に更新した数値を参照してしまうため、正常に動作しない
  time.downto(tmp_time) do |t_accepted|
    # 「許容時間がtmp_time分少ない時の価値 + tmp_value」が「現在格納されている値」よりも大きければ格納する
    if dp[t_accepted] < dp[t_accepted - tmp_time] + tmp_value
      dp[t_accepted] = dp[t_accepted - tmp_time] + tmp_value
    end
  end
end

# 最大値を出力する
puts ans.max
