#include <bits/stdc++.h>
namespace OI {
template <class T>
void rd(T &x) {
  x = 0;
  int f = 1;
  char c;
  while (!isdigit(c = getchar()))
    if (c == '-') f = -1;
  do {
    x = (x << 3) + (x << 1) + (c ^ 48);
  } while (isdigit(c = getchar()));
  x *= f;
}
template <class T>
void pt(T x) {
  if (x < 0) putchar('-'), x = -x;
  if (x > 9) pt(x / 10);
  putchar(x % 10 ^ 48);
}
}  // namespace OI
using namespace OI;
using namespace std;
const int N = 3e5 + 5;
struct node {
  int p1, p2;
  long long v;
} dp[N];
int n, m;
vector<int> Vec[4];
long long ans, tmp;
int main() {
  rd(n), rd(m);
  for (int i = 1, x, y; i <= n; i++) rd(x), rd(y), Vec[x].push_back(y);
  for (int i = 1; i <= 3; i++)
    sort(Vec[i].begin(), Vec[i].end()), reverse(Vec[i].begin(), Vec[i].end());
  for (int i = 1; i <= m; i++) {
    dp[i] = dp[i - 1];
    if (dp[i - 1].p1 < Vec[1].size() &&
        dp[i - 1].v + Vec[1][dp[i - 1].p1] > dp[i].v) {
      dp[i].v = dp[i - 1].v + Vec[1][dp[i - 1].p1];
      dp[i].p1 = dp[i - 1].p1 + 1;
      dp[i].p2 = dp[i - 1].p2;
    }
    if (i > 1 && dp[i - 2].p2 < Vec[2].size() &&
        dp[i - 2].v + Vec[2][dp[i - 2].p2] > dp[i].v) {
      dp[i].v = dp[i - 2].v + Vec[2][dp[i - 2].p2];
      dp[i].p2 = dp[i - 2].p2 + 1;
      dp[i].p1 = dp[i - 2].p1;
    }
  }
  for (int i = 0; i <= (int)Vec[3].size() && i * 3 <= m; i++) {
    ans = max(ans, tmp + dp[m - i * 3].v);
    if (i < Vec[3].size()) tmp += Vec[3][i];
  }
  pt(ans);
  return 0;
}
