#include <bits/stdc++.h>
using namespace std;
template <class T>
T sqr(T x) {
  return x * x;
}
template <class T>
T distsqr(T x, T y, T a, T b) {
  return sqr(x - a) + sqr(y - b);
}
double cosine_angle(double a, double b, double c) {
  return (double)(sqr(a) + sqr(b) - sqr(c)) / ((double)2.0 * a * b);
}
template <class T>
T Maximum(T a, T b) {
  return a > b ? a : b;
}
template <class T>
T Minimum(T a, T b) {
  return a < b ? a : b;
}
template <class T>
T GCD(T a, T b) {
  if (!b) return a;
  return GCD(b, a % b);
}
template <class T>
void SWAP(T &a, T &b) {
  T temp = a;
  a = b;
  b = temp;
  return;
}
template <class T>
T sign(T a) {
  return a < 0 ? -1 : 1;
}
template <class T>
T BigMod(T a, T n, T mod) {
  if (!n) return (T)1 % mod;
  long long int power = BigMod(a, n >> 1, mod);
  power %= mod;
  power *= power;
  power %= mod;
  if (n & 1) power *= a % mod, power %= mod;
  return power;
}
template <class T>
T ExtendedEuclid(T a, T b, T c) {
  if (!a) return 0;
  return (b * ExtendedEuclid(b % a, a, -c) + c) / a;
}
template <class T>
T ModInverse(T a, T m) {
  return ((ExtendedEuclid(a, m, (T)GCD(a, m))) % (m) + (m)) % (m);
}
struct S {
  char name[20];
  int region, score;
} player[100100];
int Comp(const void *a, const void *b) {
  S x = *(S *)a, y = *(S *)b;
  if (x.region == y.region) return y.score - x.score;
  return x.region - y.region;
}
int main() {
  int i, j, k, n, m;
  S A[3];
  scanf("%d %d", &n, &m);
  for (i = 0; i < n; i++)
    scanf("%s %d %d", player[i].name, &player[i].region, &player[i].score);
  qsort(player, n, sizeof(S), Comp);
  player[n].region = m + 1;
  for (i = j = k = 0; i < m; i++) {
    while (player[j].region == i + 1) {
      if (k < 3) {
        A[k++] = player[j];
      }
      j++;
    }
    if (k == 2)
      printf("%s %s", A[0].name, A[1].name);
    else {
      if (A[1].score == A[2].score)
        printf("?");
      else
        printf("%s %s", A[0].name, A[1].name);
    }
    k = 0;
    printf("\n");
  }
  return 0;
}
