#include using namespace std; typedef long long ll; typedef long double ld; typedef pair ii; typedef vector vi; typedef vector vvi; typedef vector vii; #define x first #define y second #define pb push_back #define eb emplace_back #define rep(i,a,b) for(auto i=(a); i<(b); ++i) #define REP(i,n) rep(i,0,n) #define all(v) begin(v), end(v) #define sz(v) ((int) (v).size()) #define rs resize #define DBG(x) cerr << __LINE__ << ": " \ << #x<< " = " << (x) << endl template ostream& operator<<(ostream &os, const vector &v) { os << "\n["; for(const T &x : v) os << x << ','; return os << "]\n"; } namespace std { template struct hash> { public: size_t operator()(const pair &p) const { size_t x = hash()(p.x), y = hash()(p.y); return x ^ (y + 0x9e3779b9 + (x<<6) + (x>>2)); } }; } ii read(ll a, ll b) { cout << "? " << a+1 << " " << b+1 << endl; ll r1, r2; cin >> r1 >> r2; return {r1-1, r2-1}; } void run() { ll n; cin >> n; vi R(n, -1); vvi Ri(n/2, {-1, -1}); vii A(n/2, {-1, -1}); vii P(n/2, {-1, -1}); vii C(n/2, {-1, -1}); ll j = 0; for (ll i = 0; i < n; i += 2) { ii r = read(i, i+1); ll a = r.x, b = r.y; if (a > b) swap(a, b); if (a == b) { R[i] = a; R[i+1] = a; Ri[a].pb(i); Ri[a].pb(i+1); continue; } P[j] = {i, i+1}; C[j] = {a, b}; if (A[a].x == -1) { A[a].x = j; } else { A[a].y = j; } if (A[b].x == -1) { A[b].x = j; } else { A[b].y = j; } j++; } for (ll i = 0; i < n/2; i++) { while (A[i].y != -1) { ll p1 = A[i].x, p2 = A[i].y; ii r = read(P[p1].x, P[p2].x); ll a = r.x, b = r.y; if ((a != C[p1].x && a != C[p1].y) || (b != C[p2].x && b != C[p2].y)) { swap(a, b); } ll a2 = C[p1].x, b2 = C[p2].x; if (a2 == a) a2 = C[p1].y; if (b2 == b) b2 = C[p2].y; if (a == b) { R[P[p1].x] = a; R[P[p2].x] = a; R[P[p1].y] = a2; R[P[p2].y] = b2; Ri[a].pb(P[p1].x); Ri[a].pb(P[p2].x); Ri[a2].pb(P[p1].y); Ri[b2].pb(P[p2].y); A[a].x = -1; A[a].y = -1; if (A[a2].x == p1) { A[a2].x = A[a2].y; A[a2].y = -1; } else { A[a2].y = -1; } if (A[b2].x == p2) { A[b2].x = A[b2].y; A[b2].y = -1; } else { A[b2].y = -1; } } else if (C[p1] == C[p2]) { ii npp1 = {P[p1].x, P[p2].x}, npp2 = {P[p1].y, P[p2].y}; P[p1] = npp1; P[p2] = npp2; } else if (a != i && b != i) { R[P[p1].y] = i; R[P[p2].y] = i; Ri[i].pb(P[p1].y); Ri[i].pb(P[p2].y); A[i].x = -1; A[i].y = -1; if (A[b].x == p2) { A[b].x = p1; } else { A[b].y = p1; } P[p1] = {P[p1].x, P[p2].x}; C[p1] = {min(a, b), max(a, b)}; } else if (a == i && b != i) { R[P[p1].y] = a2; R[P[p2].y] = i; Ri[i].pb(P[p2].y); Ri[a2].pb(P[p1].y); A[i].y = -1; if (A[a2].x == p1) { A[a2].x = A[a2].y; A[a2].y = -1; } else { A[a2].y = -1; } if (A[b].x == p2) { A[b].x = p1; } else { A[b].y = p1; } P[p1] = {P[p1].x, P[p2].x}; C[p1] = {min(a, b), max(a, b)}; } else { R[P[p1].y] = i; R[P[p2].y] = b2; Ri[i].pb(P[p1].y); Ri[b2].pb(P[p2].y); A[i].y = -1; if (A[b2].x == p2) { A[b2].x = A[b2].y; A[b2].y = -1; } else { A[b2].y = -1; } if (A[b].x == p2) { A[b].x = p1; } else { A[b].y = p1; } P[p1] = {P[p1].x, P[p2].x}; C[p1] = {min(a, b), max(a, b)}; } } } vi Pi; for (ll i = 0; i < n/2; i++) { if (P[i].x >= 0 && R[P[i].x] < 0) { Pi.pb(i); } } for (ll i = 0; i+1 < Pi.size(); i++) { ll p1 = Pi[i], p2 = Pi[i+1]; ii r = read(P[p1].x, P[p2].x); ll a = C[p1].x, a2 = C[p1].y, b = C[p2].x, b2 = C[p2].y; if (a != r.x && a != r.y) { swap(a, a2); } if (b != r.x && b != r.y) { swap(b, b2); } R[P[p1].y] = a2; R[P[p2].y] = b2; Ri[a2].pb(P[p1].y); Ri[b2].pb(P[p2].y); P[p2] = {P[p1].x, P[p2].x}; C[p2] = {min(a, b), max(a, b)}; } if (Pi.size() > 0) { ll p = Pi[Pi.size()-1]; while (C[p].x != C[p].y) { ll j1 = P[p].x; ll j2 = Ri[C[p].x][0]; ii r = read(j1, j2); if (r.x == r.y) { R[j1] = C[p].x; R[P[p].y] = C[p].y; break; } else { R[P[p].y] = C[p].x; Ri[C[p].x][0] = P[p].y; P[p] = {j1, j2}; } } } cout << "!"; for (ll i = 0; i < n; i++) { cout << " " << R[i]+1; } cout << endl; } signed main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout << fixed << setprecision(20); run(); return 0; }