// clang-format off
	#define BADSEED chrono::high_resolution_clock::now().time_since_epoch().count()
	#include <bits/stdc++.h>
	using namespace std;
	using uint = unsigned int;
	#define TM_(...) template <class __VA_ARGS__>
	#define ENABLE(...) TM_(T) static enable_if_t<__VA_ARGS__>
	#define SFINAE(name, ...)                                                  \
		TM_(, class = void) struct name##_s : false_type {};                   \
		TM_(T) struct name##_s<T, decltype(void(__VA_ARGS__))> : true_type {}; \
		TM_(T) constexpr bool name = name##_s<T>::value;
	ostream &operator<<(ostream &os, int8_t c) { return os << static_cast<int>(c); }
	namespace narut {
		TM_(T) using TupSz = tuple_size<decay_t<T>>;
		SFINAE(Iterable, begin(declval<T &>()))
		SFINAE(IsTuple, TupSz<T>{})
		SFINAE(Coutable, cout << declval<T &>())
		SFINAE(Cinable, cin >> declval<T &>())
		TM_(T) constexpr char Spc(T &&) { return (Iterable<T> or IsTuple<T>) ? '\n' : ' '; }
		template <ostream &os, bool Red> struct Writer {
			ENABLE(Coutable<T>) Write(T const &t) { os << t; }
			ENABLE(!Coutable<T> and Iterable<T>) Write(T const &t) {
				auto it = begin(t), e = end(t);
				if (it != e) Write(*it++);
				for (; it != e; Write(*it++)) os << Spc(*it);
			}
			TM_(T, size_t... Is) static void WriteTup(T const &t, index_sequence<Is...>) {
				(void)(int[]){0, ((Is == 0) ? 0 : ((os << ' '), 0), Write(get<Is>(t)), 0)...};
			}
			ENABLE(!Coutable<T> and !Iterable<T> and IsTuple<T>) Write(T const &t) {
				WriteTup(t, make_index_sequence<TupSz<T>::value>{});
			}
			void operator()() const { os << '\n'; }
			TM_(F, class... Ts) void operator()(F const &f, Ts const &... ts) {
				if (Red) os << "\033[0;31m";
				Write(f);
				(void)(int[]){0, (os << ' ', Write(ts), 0)...};
				if (Red)
					os << "\033[0m\n";
				else
					os << '\n';
			}
		};
		struct Cin {
			ENABLE(Cinable<T>) Read(T &t) { cin >> t; }
			ENABLE(!Cinable<T> and Iterable<T>) Read(T &t) {
				for (auto &&x : t) Read(x);
			}
			TM_(T, size_t... Is) static void ReadTup(T &t, index_sequence<Is...>) {
				(void)(int[]){0, (Read(get<Is>(t)), 0)...};
			}
			ENABLE(!Cinable<T> and !Iterable<T> and IsTuple<T>) Read(T &t) {
				ReadTup(t, make_index_sequence<TupSz<T>::value>{});
			}
			TM_(T) void operator()(T &t) const { Read(t); }
			TM_(T) void operator()(T &t, uint n) const { t.resize(n), Read(t); }
			TM_(T) operator T() const {
				T t;
				return Read(t), t;
			}
		};
		struct Big {
			TM_(T) constexpr operator T() const {
				return 0x3f3f3f3f3f3f3f3f & numeric_limits<T>::max();
			}
		};
		TM_(T, size_t N, size_t... Ns) struct arr {
			using type = array<typename arr<T, Ns...>::type, N>;
		};
		TM_(T, size_t N) struct arr<T, N> { using type = array<T, N>; };
		TM_(T, size_t N, size_t... Ns) using Arr = typename arr<T, N, Ns...>::type;
		template <class C, class T> auto Fill(C &c, T const &t) -> decltype(void(*begin(c) = t)) {
			fill(begin(c), end(c), t);
		}
		template <class C, class T> auto Fill(C &c, T const &t) -> decltype(void(begin(*begin(c)))) {
			for (auto &x : c) Fill(x, t);
		}
	} // namespace narut
	narut::Cin Cin;
	narut::Writer<cout, false> Cout;
	narut::Big Big;
	using narut::Arr;
	using narut::Fill;
	using ll = long long;
	#define FOR(i, j, n) for (int i = static_cast<int>(j); i < static_cast<int>(n); ++i)
	#define ROF(i, j, n) for (int i = static_cast<int>(n) - 1; i >= static_cast<int>(j); --i)
	#ifdef NARUT_LOCAL
	narut::Writer<cerr, true> Cerr;
	#define DBG(...) __VA_ARGS__
	#define Debug(...) Cerr(__VA_ARGS__)
	#else
	#define Debug(...) 0
	#define DBG(...)
	#endif
	#ifndef BADSEED
	#define BADSEED random_device{}()
	#endif

// clang-format on
// STUCK : READ THE PROBLEM CAREFULLY. LOOK AT ALL THE CONSTRAINTS


// auto rmq = RangeQuery<int>(v.begin(), v.end());
template <class T> struct RangeQuery {
	RangeQuery() = default;
	RangeQuery(uint n) : sz(getSz(n)), tree(2 * sz) {}
	template <class It> RangeQuery(It first, It last) : sz(getSz((last - first))) {
		tree.reserve(2 * sz), tree.resize(sz);
		tree.insert(tree.end(), first, last), tree.resize(2 * sz);
		build();
	}

	void Set(uint u, const T &elem) {
		u += sz;
		tree[u] = elem;
		for (u /= 2; u > 0; u /= 2) tree[u] = tree[2 * u] + tree[2 * u + 1];
	}

	T QueryExc(uint l, uint r) const { // [l, r)
		T left{}, right{};
		for (l += sz, r += sz; l < r; l /= 2, r /= 2) {
			if (l % 2) left = left + tree[l++];
			if (r % 2) right = tree[--r] + right;
		}
		return left + right;
	}

	T QueryInc(uint l, uint r) { return QueryExc(l, r + 1); }
	const T &operator[](uint u) const { return tree[u + sz]; }

	// template <bool State = true, class F> int FindLeft(F func) const {
	// 	if (!func(tree[1])) return -1;
	// 	[[maybe_unused]] conditional_t<State, T, int> state{};
	// 	uint u = 1;
	// 	while (u < sz) {
	// 		if constexpr (State) {
	// 			const auto new_state = state + tree[2 * u];
	// 			if (func(new_state))
	// 				u *= 2;
	// 			else
	// 				u = 2 * u + 1, state = new_state;
	// 		} else {
	// 			if (func(tree[2 * u]))
	// 				u *= 2;
	// 			else
	// 				u = 2 * u + 1;
	// 		}
	// 	}
	// 	return u - sz;
	// }

	// template <bool State = true, class F> int FindRight(F func) const {
	// 	if (!func(tree[1])) return -1;
	// 	[[maybe_unused]] conditional_t<State, T, int> state{};
	// 	uint u = 1;
	// 	while (u < sz) {
	// 		if constexpr (State) {
	// 			const auto new_state = tree[2 * u + 1] + state;
	// 			if (func(new_state))
	// 				u = 2 * u + 1;
	// 			else
	// 				u *= 2, state = new_state;
	// 		} else {
	// 			if (func(tree[2 * u + 1]))
	// 				u = 2 * u + 1;
	// 			else
	// 				u *= 2;
	// 		}
	// 	}
	// 	return u - sz;
	// }

  private:
	uint sz = 0;
	vector<T> tree;
	static uint getSz(uint n) {
		if (n < 2) return 1;
		return 1u << (sizeof(uint) * 8 - __builtin_clz(n - 1));
	}
	void build() {
		for (uint i = sz - 1; i; --i) tree[i] = tree[2 * i] + tree[2 * i + 1];
	}
};

struct MinE {
	int pos = -1;
	int val = Big;

	MinE operator+(MinE rhs) const {
		if (make_pair(val, -pos) < make_pair(rhs.val, -rhs.pos)) return *this;
		return rhs;
	}
};




auto Run()
{
	int n, m;
	cin>>n>>m;
	vector<pair<int, int> > AB(n);
	Cin(AB);

	sort(rbegin(AB), rend(AB), [](pair<int, int> lhs, pair<int, int> rhs){
		return make_pair(lhs.second, -lhs.first) < make_pair(rhs.second, -lhs.first);
	});
	

	vector<MinE> data(m);
	FOR(i,0,m) {
		data[i].pos = i;
		data[i].val = 0;
	}

	RangeQuery<MinE> rq(data.begin(), data.end());

	for (auto const&p : AB) {
		int a, b;
		tie(a,b) = p;

		int latest = m-a;
		if (latest < 0) continue;
		auto me = rq.QueryInc(0, latest);
		Debug(a, b, ':', me.pos, me.val);
		if (me.pos == -1) continue;		
		if (b <= me.val) continue;		
		auto e = MinE{me.pos, b};
		data[me.pos] = e;
		rq.Set(me.pos, e);
	}
	
	ll ans = 0;
	for (auto&d:data) {
		ans += d.val;
	}
	cout << ans;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(10);
#ifdef NARUT_LOCAL
	cerr << fixed << setprecision(10);
	assert(freopen("./io/test.in", "r", stdin));
	// assert(freopen("./io/test.out", "w", stdout));
#endif

	Run();
}


Measured memory_bytes: 3840