#define _USE_MATH_DEFINES #include using namespace std; #define FOR(i,m,n) for(int i=(m);i<(n);++i) #define REP(i,n) FOR(i,0,n) #define ALL(v) (v).begin(),(v).end() using ll = long long; constexpr int INF = 0x3f3f3f3f; constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL; constexpr double EPS = 1e-8; constexpr int MOD = 1000000007; // constexpr int MOD = 998244353; constexpr int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1}; constexpr int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1}; template inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; } template inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; } struct IOSetup { IOSetup() { std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); std::cout << fixed << setprecision(20); } } iosetup; pair query(int i, int j) { cout << "? " << i + 1 << ' ' << j + 1 << endl; int p, q; cin >> p >> q; return {p, q}; } int main() { int n; cin >> n; map>, pair> mp; FOR(si, 1, n) REP(sj, n) { vector> v; FOR(i, 1, n) REP(j, n) { if (i != si || j != sj) v.emplace_back(minmax(si - i, sj - j)); } sort(ALL(v)); mp[v] = {si, sj}; } int m = n * n - n; vector> res(m), sea; FOR(i, 1, m) { auto [p, q] = query(0, i); res[i] = {p, q}; sea.emplace_back(p, q); } sort(ALL(sea)); vector> ans(m, {-1, -1}); ans[0] = mp[sea]; map, vector>> mp2; map, int> rev; rev[ans[0]] = 0; FOR(i, 1, n) REP(j, n) { if (i != ans[0].first || j != ans[0].second) mp2[minmax(ans[0].first - i, ans[0].second - j)].emplace_back(i, j); } FOR(idx, 1, m) { if (mp2[res[idx]].size() == 1) { ans[idx] = mp2[res[idx]][0]; rev[ans[idx]] = idx; } } FOR(idx, 1, m) { if (mp2[res[idx]].size() == 2) { auto [p1, q1] = mp2[res[idx]][0]; auto [p2, q2] = mp2[res[idx]][1]; for (auto [pr, pos] : rev) { auto [p, q] = pr; if (minmax(p - p1, q - q1) != minmax(p - p2, q - q2)) { auto [res_p, res_q] = query(pos, idx); if (res_p == minmax(p - p1, q - q1).first && res_q == minmax(p - p1, q - q1).second) { ans[idx] = {p1, q1}; mp2[res[idx]].erase(mp2[res[idx]].begin()); } else { assert(res_p == minmax(p - p2, q - q2).first && res_q == minmax(p - p2, q - q2).second); ans[idx] = {p2, q2}; mp2[res[idx]].erase(mp2[res[idx]].begin() + 1); } // rev[ans[idx]] = idx; break; } } } else { ans[idx] = mp2[res[idx]][0]; // rev[ans[idx]] = idx; } } cout << "! "; REP(i, m) { cout << ans[i].first * n + ans[i].second; if (i + 1 == m) { cout << endl; } else { cout << ' '; } } return 0; }