#!/usr/bin/env python3 import sys import random # 1. Make pairs (1, 2), (3, 4), ... # 2. Repeatedly find pairs with [at least] one overlap. # 3. Resolve these pairs, 25% probability of hitting the duplicates. # 4. Resolve all remaining pairs. def debug(*args): return print(*args, file=sys.stderr) n = int(input()) k = n // 2 values = [None] * n # Maps value to list of 2 positions posof = [[] for _ in range(k)] pairedwith = [None] * n perm = list(range(n)) random.shuffle(perm) iperm = [0] * n for i, j in enumerate(perm): iperm[j] = i def query(i, j): assert i != j print("?", perm[i] + 1, perm[j] + 1, flush=True) a, b = [int(x) - 1 for x in input().split()] set(i, a) set(j, b) return a, b def matchingpos(pos): return sum(posof[values[pos]]) - pos def fix(*ps): debug("fix", *[x + 1 for x in ps]) for pos in ps: pairedwith[pos] = pos def make_pair(i, j): debug("make pair", i + 1, j + 1) pairedwith[i] = j pairedwith[j] = i def set(pos, val, remove=True): debug("set", pos + 1, val + 1) try: posof[values[pos]].remove(pos) except: pass posof[val].append(pos) values[pos] = val # Solve pair containing i has xy and pair containing j has xy. def xyxy(i2, i, j, j2): debug("xyxy", i2 + 1, i + 1, j + 1, j2 + 1) assert i2 != i assert i2 != j assert i2 != j2 assert i != j assert i != j2 assert j != j2 x = values[i] y = values[i2] a, b = query(i, j) if a == b: set(i2, x + y - a) set(j2, x + y - b) fix(i, i2, j, j2) return set(i2, a) set(j2, b) xyxy(i, j, i2, j2) # x=y is allowed here def wxyz(i2, i, j, j2): debug("wxyz", i2 + 1, i + 1, j + 1, j2 + 1) w, x, y, z = values[i2], values[i], values[j], values[j2] debug(w, x, y, z) for k in [i2, i, j, j2]: assert pairedwith[k] != k if x == y and w == z: return xyxy(i2, i, j, j2) if w == y: i2, i = i, i2 if x == z: j2, j = j, j2 if w == z: i2, i = i, i2 j2, j = j, j2 w, x, y, z = values[i2], values[i], values[j], values[j2] assert w not in [x, y, z] assert x not in [z] assert y not in [z] a, b = query(i, j) if a == b: fix(i, j, i2, j2) else: set(i2, w if w not in [a, b] else x) set(j2, z if z not in [a, b] else y) fix(i2, j2) make_pair(i, j) return (i, j) for i in range(0, n, 2): a, b = query(i, i + 1) if a == b: fix(i, i + 1) else: make_pair(i, i + 1) r = None def add_remaining(pr): global r debug("add remaining", pr) if not r: r = pr return r = wxyz(r[0], r[1], pr[0], pr[1]) debug(values) # Find values that don't have any fixed position yet, and query the 2 pairs. for _ in range(3): for i in range(n): j = matchingpos(i) i2 = pairedwith[i] j2 = pairedwith[j] if i2 == i or j2 == j: continue if r and (i in r or j in r): r = None pr = wxyz(i2, i, j, j2) if pr: add_remaining(pr) for i in range(n): i2 = pairedwith[i] if i2 == i: continue add_remaining((i, i2)) # Resolve the last remaining if needed if r: xyxy(r[0], r[1], matchingpos(r[1]), matchingpos(r[0])) print("!", *[values[iperm[i]] + 1 for i in range(n)])