#include <bits/stdc++.h>
using namespace std;
template <class T>
bool umin(T& a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool umax(T& a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
int n, m;
long long par[300009], dp[300009];
pair<int, int> pnt[300009];
vector<int> adj[3];
long long solve(int x) {
  if (m < x * 3) return 0;
  return dp[m - x * 3] + par[x];
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < 3; i++) adj[i].push_back(1000000007);
  while (n--) {
    int w, c;
    scanf("%d%d", &w, &c);
    adj[w - 1].push_back(c);
  }
  for (int i = 0; i < 3; i++) {
    sort(adj[i].begin(), adj[i].end());
    reverse(adj[i].begin(), adj[i].end());
    adj[i][0] = 0;
  }
  for (int i = 1; i < (int)adj[2].size(); i++) par[i] = par[i - 1] + adj[2][i];
  for (int i = 0; i < ((int)adj[0].size() + (int)adj[1].size() * 2 - 3); i++) {
    int p0 = pnt[i].first, p1 = pnt[i].second;
    if (!p0 and !p1 and i) continue;
    if (p0 + 1 < int(adj[0].size()) and umax(dp[i + 1], dp[i] + adj[0][p0 + 1]))
      pnt[i + 1] = make_pair(p0 + 1, p1);
    if (p1 + 1 < int(adj[1].size()) and p0 + 2 < int(adj[0].size())) {
      if (adj[1][p1 + 1] > adj[0][p0 + 1] + adj[0][p0 + 2])
        dp[i + 2] = dp[i] + adj[1][p1 + 1], pnt[i + 2] = make_pair(p0, p1 + 1);
      else
        dp[i + 2] = dp[i] + adj[0][p0 + 1] + adj[0][p0 + 2],
               pnt[i + 2] = make_pair(p0 + 2, p1);
    } else if (p1 + 1 < int(adj[1].size()))
      dp[i + 2] = dp[i] + adj[1][p1 + 1], pnt[i + 2] = make_pair(p0, p1 + 1);
    else if (p0 + 2 < int(adj[0].size()))
      dp[i + 2] = dp[i] + adj[0][p0 + 1] + adj[0][p0 + 2],
             pnt[i + 2] = make_pair(p0 + 2, p1);
  }
  for (int i = 1; i < 300009; i++) umax(dp[i], dp[i - 1]);
  long long ans = 0;
  for (int i = 0; i < int(adj[2].size()); i++) umax(ans, solve(i));
  printf("%lld\n", ans);
  return 0;
}
