// Original C++ solution (slower):
    #include <iostream>

    #include <iomanip>

    #include <string>

    #include <cmath>

    #include <algorithm>

    #include <vector>

    #include <set>

    #include <map>

    #include <unordered_map>

    #include <unordered_set>

    #include <list>

    #include <stack>

    #include <queue>

    #include <bitset>

    #include <numeric>

    #include <cassert>

    #include <random>

    #ifdef DEBUG

    #include "./Lib/debug.hpp"

    #include "./Lib/Timer.h"

    #else

    #define dump(...)

    template<class T>inline auto d_val(T a, T b) { return a; }

    #endif

     

    /* (=＾o＾=) */

    #define int ll

     

    /* macro */

    #define FOR(i, b, e) for(ll i = (ll)(b); i < (ll)(e); ++i)

    #define RFOR(i, b, e) for(ll i = (ll)(e-1); i >= (ll)(b); --i)

    #define REP(i, n) FOR(i, 0, n)

    #define RREP(i, n) RFOR(i, 0, n)

    #define REPC(x,c) for(const auto& x:(c))

    #define REPI2(it,b,e) for(auto it = (b); it != (e); ++it)

    #define REPI(it,c) REPI2(it, (c).begin(), (c).end())

    #define RREPI(it,c) REPI2(it, (c).rbegin(), (c).rend())

    #define REPI_ERACE2(it, b, e) for(auto it = (b); it != (e);)

    #define REPI_ERACE(it, c) REPI_ERACE2(it, (c).begin(), (c).end())

    #define ALL(x) (x).begin(),(x).end()

    #define cauto const auto&

    /* macro func */

    #define SORT(x) do{sort(ALL(x));}while(false)

    #define RSORT(x) do{sort((x).rbegin(),(x).rend());}while(false)

    #define UNIQUE(v) do{v.erase( unique(v.begin(), v.end()), v.end() );}while(false)

    #define MAX(x,y) do{x = std::max(x,y);}while(false)

    #define MIN(x,y) do{x = std::min(x,y);}while(false)

    #define BR do{cout<<"\n";}while(false)

     

    /* type define */

    using ll = long long;

    using PAIR = std::pair<ll, ll>;

    using VS = std::vector<std::string>;

    using VL = std::vector<long long>;

    using VVL = std::vector<VL>;

    using VVVL = std::vector<VVL>;

    using VD = std::vector<double>;

    template<class T>

    using V = std::vector<T>;

     

    /* using std */

    using std::cout;

    constexpr char endl = '\n';

    using std::cin;

    using std::sort;

    using std::pair;

    using std::string;

    using std::stack;

    using std::queue;

    using std::vector;

    using std::list;

    using std::map;

    using std::unordered_map;

    using std::multimap;

    using std::unordered_multimap;

    using std::set;

    using std::unordered_set;

    using std::unordered_multiset;

    using std::multiset;

    using std::bitset;

    using std::priority_queue;

     

    /* constant value */

    constexpr ll MOD = 1000000007;

    //constexpr ll MOD = 998244353;

     

    /* Initial processing  */

    struct Preprocessing { Preprocessing() { std::cin.tie(0); std::ios::sync_with_stdio(0); }; }_Preprocessing;

     

    /* Remove the source of the bug */

    signed pow(signed, signed) { assert(false); return -1; }

     

    /* define hash */

    namespace std { template <>	class hash<std::pair<ll, ll>> { public:	size_t operator()(const std::pair<ll, ll>& x) const { return hash<ll>()(1000000000 * x.first + x.second); } }; }

     

    /* input */

    template<class T> std::istream& operator >> (std::istream& is, vector<T>& vec) { for (T& x : vec) is >> x; return is; }

     

    //=============================================================================================

     

     

    signed main() {

    	ll n, t;

    	cin >> n >> t;

    	V<PAIR> v; v.reserve(n);

    	REP(_, n) {

    		ll a, b; cin >> a >> b; v.emplace_back(a, b);

    	}

     

    	ll ans = 0;

    	{

    		sort(ALL(v), [](cauto a, cauto b) {

    			if (a.second == b.second) {

    				return a.first < b.first;

    			}

    			return a.second < b.second;

    		});

     

    		VL dp(t + 1);

    		REPC(p, v) {

    			MAX(dp[t], dp[t - 1] + p.second);

    			RREP(i, t) {

    				if (i + p.first < t + 1) {

    					MAX(dp[i + p.first], dp[i] + p.second);

    				}

    			}

    		}

    		MAX(ans, dp[t]);

    	}

    	{

    		sort(ALL(v), [](cauto a, cauto b) {

    			if (a.second == b.second) {

    				return a.first < b.first;

    			}

    			return a.second > b.second;

    		});

     

    		VL dp(t + 1);

    		REPC(p, v) {

    			MAX(dp[t], dp[t - 1] + p.second);

    			RREP(i, t) {

    				if (i + p.first < t + 1) {

    					MAX(dp[i + p.first], dp[i] + p.second);

    				}

    			}

    		}

    		MAX(ans, dp[t]);

    	}

    	{

    		sort(ALL(v), [](cauto a, cauto b) {

    			if (a.second == b.second) {

    				return a.first < b.first;

    			}

    			return a.second > b.second;

    		});

     

    		VL dp(t + 1);

    		REPC(p, v) {

    			MAX(dp[t], dp[t - 1] + p.second);

    			RREP(i, t) {

    				if (i + p.first < t + 1) {

    					MAX(dp[i + p.first], dp[i] + p.second);

    				}

    			}

    		}

    		MAX(ans, dp[t]);

    	}

    	{

    		sort(ALL(v), [](cauto a, cauto b) {

    			if (a.second == b.second) {

    				return a.first > b.first;

    			}

    			return a.second < b.second;

    		});

     

    		VL dp(t + 1);

    		REPC(p, v) {

    			MAX(dp[t], dp[t - 1] + p.second);

    			RREP(i, t) {

    				if (i + p.first < t + 1) {

    					MAX(dp[i + p.first], dp[i] + p.second);

    				}

    			}

    		}

    		MAX(ans, dp[t]);

    	}

    	std::random_device seed;

    	auto mnt = std::mt19937_64(seed());

    	REP(_, 150) {

     

    		std::shuffle(ALL(v), mnt);

    		dump(v);

     

    		VL dp(t + 1);

    		REPC(p, v) {

    			MAX(dp[t], dp[t - 1] + p.second);

    			RREP(i, t) {

    				if (i + p.first < t + 1) {

    					MAX(dp[i + p.first], dp[i] + p.second);

    				}

    			}

    		}

    		MAX(ans, dp[t]);

    	}

     

    	cout << ans << endl;

    }

// Optimized solution to the same problem (faster):
#include <iostream>

#include <iomanip>

#include <string>

#include <cmath>

#include <algorithm>

#include <vector>

#include <set>

#include <map>

#include <unordered_map>

#include <unordered_set>

#include <list>

#include <stack>

#include <queue>

#include <bitset>

#include <numeric>

#include <cassert>

#include <random>

#ifdef DEBUG

#include "./Lib/debug.hpp"

#include "./Lib/Timer.h"

#else

#define dump(...)

template<class T>inline auto d_val(T a, T b) { return a; }

#endif



/* (=＾o＾=) */

#define int ll



/* macro */

#define FOR(i, b, e) for(ll i = (ll)(b); i < (ll)(e); ++i)

#define RFOR(i, b, e) for(ll i = (ll)(e-1); i >= (ll)(b); --i)

#define REP(i, n) FOR(i, 0, n)

#define RREP(i, n) RFOR(i, 0, n)

#define REPC(x,c) for(const auto& x:(c))

#define REPI2(it,b,e) for(auto it = (b); it != (e); ++it)

#define REPI(it,c) REPI2(it, (c).begin(), (c).end())

#define RREPI(it,c) REPI2(it, (c).rbegin(), (c).rend())

#define REPI_ERACE2(it, b, e) for(auto it = (b); it != (e);)

#define REPI_ERACE(it, c) REPI_ERACE2(it, (c).begin(), (c).end())

#define ALL(x) (x).begin(),(x).end()

#define cauto const auto&

/* macro func */

#define SORT(x) do{sort(ALL(x));}while(false)

#define RSORT(x) do{sort((x).rbegin(),(x).rend());}while(false)

#define UNIQUE(v) do{v.erase( unique(v.begin(), v.end()), v.end() );}while(false)

#define MAX(x,y) do{x = std::max(x,y);}while(false)

#define MIN(x,y) do{x = std::min(x,y);}while(false)

#define BR do{cout<<"\n";}while(false)



/* type define */

using ll = long long;

using PAIR = std::pair<ll, ll>;

using VS = std::vector<std::string>;

using VL = std::vector<long long>;

using VVL = std::vector<VL>;

using VVVL = std::vector<VVL>;

using VD = std::vector<double>;

template<class T>

using V = std::vector<T>;



/* using std */

using std::cout;

constexpr char endl = '\n';

using std::cin;

using std::sort;

using std::pair;

using std::string;

using std::stack;

using std::queue;

using std::vector;

using std::list;

using std::map;

using std::unordered_map;

using std::multimap;

using std::unordered_multimap;

using std::set;

using std::unordered_set;

using std::unordered_multiset;

using std::multiset;

using std::bitset;

using std::priority_queue;



/* constant value */

constexpr ll MOD = 1000000007;

//constexpr ll MOD = 998244353;



/* Initial processing  */

struct Preprocessing { Preprocessing() { std::cin.tie(0); std::ios::sync_with_stdio(0); }; }_Preprocessing;



/* Remove the source of the bug */

signed pow(signed, signed) { assert(false); return -1; }



/* define hash */

namespace std { template <>	class hash<std::pair<ll, ll>> { public:	size_t operator()(const std::pair<ll, ll>& x) const { return hash<ll>()(1000000000 * x.first + x.second); } }; }



/* input */

template<class T> std::istream& operator >> (std::istream& is, vector<T>& vec) { for (T& x : vec) is >> x; return is; }



//=============================================================================================





signed main() {

	ll n, t;

	cin >> n >> t;

	V<PAIR> v; v.reserve(n);

	REP(_, n) {

		ll a, b; cin >> a >> b; v.emplace_back(a, b);

	}



	ll ans = 0;

	{

		sort(ALL(v), [](cauto a, cauto b) {

			if (a.first == b.first) {

				return a.second < b.second;

			}

			return a.first < b.first;

		});



		VL dp(t + 1);

		REPC(p, v) {

			MAX(dp[t], dp[t - 1] + p.second);

			RREP(i, t) {

				if (i + p.first < t + 1) {

					MAX(dp[i + p.first], dp[i] + p.second);

				}

			}

		}

		MAX(ans, dp[t]);

	}

	cout << ans << endl;

}


// Fastest known solution for this problem: