#include <bits/stdc++.h>
using namespace std;
template <typename T>
istream& operator>>(istream& I, vector<T>& v) {
  for (auto& i : v) I >> i;
  return I;
}
template <typename T>
ostream& operator<<(ostream& O, vector<T>& v) {
  for (auto& i : v) O << i << ' ';
  return O;
}
template <typename T>
istream& operator>>(istream& I, vector<vector<T>>& v) {
  for (auto& i : v)
    for (auto& x : i) I >> x;
  return I;
}
template <typename T>
ostream& operator<<(ostream& O, vector<vector<T>>& v) {
  for (auto& i : v) {
    for (auto& x : i) O << x << ' ';
    O << '\n';
  }
  return O;
}
template <typename T, typename U>
istream& operator>>(istream& I, pair<T, U>& p) {
  I >> p.first >> p.second;
  return I;
}
template <typename T, typename U>
ostream& operator<<(ostream& O, pair<T, U>& p) {
  O << p.first << ' ' << p.second;
  return O;
}
const int maxn = 1e6 + 3;
const int mod = 1e9 + 7;
using namespace std;
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  ;
  int n, m;
  cin >> n >> m;
  string name;
  int region, score;
  vector<pair<int, string>> v[m];
  for (int i = 0; i < n; ++i) {
    cin >> name >> region >> score;
    --region;
    v[region].push_back({score, name});
  }
  for (int i = 0; i < m; ++i) {
    sort(v[i].begin(), v[i].end());
    reverse(v[i].begin(), v[i].end());
    auto& query = v[i];
    if (query.size() == 2 || query[2].first < query[1].first) {
      cout << query[0].second << " " << query[1].second << "\n";
    } else {
      cout << "?"
           << "\n";
    }
  }
}
