#include <bits/stdc++.h>
using namespace std;
struct Node {
  long long v, n1, n2;
} dp[500000];
long long prefix3[500000], a1[500000], a2[500000], a3[500000], tot1, tot2, tot3,
    ans, n, m;
inline long long read() {
  register long long s = 0, w = 1;
  register char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') w = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    s = (s << 3) + (s << 1) + (ch ^ 48);
    ch = getchar();
  }
  return s * w;
}
inline bool cmp(long long x, long long y) { return x > y; }
signed main() {
  n = read(), m = read();
  for (register long long i = 1; i <= n; i++) {
    long long x = read(), y = read();
    if (x == 1) a1[++tot1] = y;
    if (x == 2) a2[++tot2] = y;
    if (x == 3) a3[++tot3] = y;
  }
  sort(a1 + 1, a1 + tot1 + 1, cmp);
  sort(a2 + 1, a2 + tot2 + 1, cmp);
  sort(a3 + 1, a3 + tot3 + 1, cmp);
  for (register long long i = 1; i <= tot3; i++)
    prefix3[i] = prefix3[i - 1] + a3[i];
  for (register long long i = 1; i <= m; i++) {
    dp[i] = dp[i - 1];
    if (dp[i].v < dp[i - 1].v + a1[dp[i - 1].n1 + 1]) {
      dp[i].v = dp[i - 1].v + a1[dp[i - 1].n1 + 1];
      dp[i].n1 = dp[i - 1].n1 + 1, dp[i].n2 = dp[i - 1].n2;
    }
    if (i >= 2 && dp[i].v < dp[i - 2].v + a2[dp[i - 2].n2 + 1]) {
      dp[i].v = dp[i - 2].v + a2[dp[i - 2].n2 + 1];
      dp[i].n1 = dp[i - 2].n1, dp[i].n2 = dp[i - 2].n2 + 1;
    }
  }
  for (register long long i = 0; i <= tot3 && i * 3 <= m; i++)
    ans = max(ans, dp[m - i * 3].v + prefix3[i]);
  printf("%lld\n", ans);
  return 0;
}
