#include <bits/stdc++.h>
using namespace std;
template <class T1, class T2>
inline istream& operator>>(istream& fin, pair<T1, T2>& pr) {
  fin >> pr.first >> pr.second;
  return fin;
}
template <class T0, class T1, class T2>
inline istream& operator>>(istream& fin, tuple<T0, T1, T2>& t) {
  fin >> get<0>(t) >> get<1>(t) >> get<2>(t);
  return fin;
}
template <class T>
inline istream& operator>>(istream& fin, vector<T>& a) {
  for (auto& u : a) fin >> u;
  return fin;
}
template <class T, size_t n>
inline istream& operator>>(istream& fin, array<T, n>& a) {
  for (auto& u : a) fin >> u;
  return fin;
}
int f542() {
  size_t n, time;
  cin >> n >> time;
  typedef struct {
    size_t buf, val;
  } value_t;
  const auto comp = [](const value_t& a, const value_t& b) {
    return a.buf < b.buf || (a.buf == b.buf && a.val < b.val);
  };
  priority_queue<value_t, vector<value_t>, decltype(comp)> heap(comp);
  for (size_t i = 0; i < n; ++i) {
    size_t val, lag;
    cin >> lag >> val;
    if (lag < time + 1) heap.push({time - lag, val});
  }
  size_t val = 0;
  while (!heap.empty()) {
    const auto top = heap.top();
    heap.pop();
    if (top.buf == 0 || heap.empty())
      val = max(val, top.val);
    else {
      const auto next = heap.top();
      if (top.buf != next.buf)
        heap.push({next.buf, top.val});
      else {
        heap.pop();
        heap.push({top.buf - 1, top.val + next.val});
      }
    }
  }
  return val;
}
int main(const int argc, char* argv[]) {
  cout << f542();
  return EXIT_SUCCESS;
}
