#include using namespace std; int main() { int n; cin >> n; int m = n * (n - 1); vector dx(m), dy(m); for (int i = 1; i < m; i++) { cout << "? " << i + 1 << " " << 1 << endl; cin >> dx.at(i) >> dy.at(i); } int dxmax = *max_element(dx.begin(), dx.end()), dymax = *max_element(dy.begin(), dy.end()), dxmin = *min_element(dx.begin(), dx.end()), dymin = *min_element(dy.begin(), dy.end()); if (dxmax - dxmin < n - 1) { swap(dxmax, dymax); swap(dxmin, dymin); for (int i = 0; i < m; i++) { swap(dx.at(i), dy.at(i)); } } assert(dxmax - dxmin == n - 1); assert(dymax - dymin == n - 2); map, bool> twoway; vector index(n, vector(n - 1, -1)); for (int i = 0; i < m; i++) { if (index.at(dx.at(i) - dxmin).at(dy.at(i) - dymin) != -1) { twoway[{dx.at(i), dy.at(i)}] = true; swap(dx.at(i), dy.at(i)); twoway[{dx.at(i), dy.at(i)}] = true; } index.at(dx.at(i) - dxmin).at(dy.at(i) - dymin) = i; } int base = -1; for (int i = 0; i < m; i++) { if (dxmin != dymin and dx.at(i) == dxmin and dy.at(i) == dymin) { base = i; break; } if (dxmin == dymin and dx.at(i) == dxmax and dy.at(i) == dymax) { base = i; break; } } vector visited(m); for (int i = 0; i < m; i++) { if (visited.at(i)) continue; if (not twoway[{dx.at(i), dy.at(i)}]) continue; assert(i == index.at(dx.at(i) - dxmin).at(dy.at(i) - dymin)); int co_i = index.at(dy.at(i) - dxmin).at(dx.at(i) - dymin); cout << "? " << i + 1 << " " << base + 1 << endl; int dxbase, dybase; cin >> dxbase >> dybase; if (dx.at(i) != dxbase + dx.at(base)) { swap(dx.at(i), dy.at(i)); } if (dx.at(i) != dxbase + dx.at(base)) { swap(dxbase, dybase); } if (dx.at(i) != dxbase + dx.at(base)) { swap(dx.at(i), dy.at(i)); } assert(dx.at(i) == dxbase + dx.at(base)); assert(dy.at(i) == dybase + dy.at(base)); dx.at(co_i) = dy.at(i); dy.at(co_i) = dx.at(i); visited.at(co_i) = true; } cout << "!"; for (int i = 0; i < m; i++) { cout << " " << n * (dy.at(i) - dymin) + (dx.at(i) - dxmin) + n; } cout << endl; }