#include <bits/stdc++.h>
template <typename T>
struct SMAWK {
  std::vector<std::pair<int, T>> minima;
  std::function<T(int, int)> oracle;
  std::vector<std::unordered_map<int, T>> memo;
  T query(int i, int j) {
    auto it = memo[i].find(j);
    if (it != memo[i].end()) return it->second;
    return memo[i][j] = oracle(i, j);
  }
  void smawk_rec(const std::vector<int> &js, int ib, int ie, int id) {
    if (ib > ie) return;
    std::vector<int> js2;
    int i = ib;
    for (int j : js) {
      while (!js2.empty() && query(i, js2.back()) > query(i, j)) {
        js2.pop_back();
        i -= id;
      }
      if (int(js2.size()) != (ie - ib) / id) {
        js2.push_back(j);
        i += id;
      }
    }
    smawk_rec(js2, ib + id, ie, id << 1);
    for (int i = ib, q = 0; i <= ie; i += id << 1) {
      int jt = (i + id <= ie ? minima[i + id].first : js.back());
      T fm = std::numeric_limits<T>::max();
      for (; q < int(js.size()); ++q) {
        T fq = query(i, js[q]);
        if (fm > fq) {
          fm = fq;
          minima[i] = {js[q], fq};
        }
        if (js[q] == jt) break;
      }
    }
  }
  SMAWK(int N, int M, std::function<T(int, int)> _oracle)
      : minima(N), oracle(_oracle), memo(N) {
    std::vector<int> js(M);
    std::iota(js.begin(), js.end(), 0);
    smawk_rec(js, 0, N - 1, 1);
  }
};
int main() {
  using namespace std;
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, m;
  cin >> n >> m;
  auto query = [](int i, int j) {
    cout << "? " << i + 1 << ' ' << j + 1 << endl;
    cin >> i;
    return i;
  };
  int ans = numeric_limits<int>::max();
  for (auto [i, v] : SMAWK<int>(n, m, query).minima) ans = min(ans, v);
  cout << "! " << ans << endl;
}
