#!/usr/bin/env python3
import sys
import random

n = int(input())

perm = list(range(n))
random.shuffle(perm)
iperm = [0] * n
for i, j in enumerate(perm):
    iperm[j] = i


def query(a, b):
    print("?", perm[a] + 1, perm[b] + 1, flush=True)
    x, y = map(int, input().split())
    return (x, y)


# Integer, or pair of ((position1, position2), (value1, value2))
ans = [None] * n
# Positions where i may occur.
# list of (int or (int, int))
pos = {i: [] for i in range(n)}
for i in range(0, n, 2):
    x, y = query(i, i + 1)
    # force x <= y
    if x > y:
        x, y = y, x
    if x == y:
        ans[i] = ans[i + 1] = x
        continue
    ans[i] = ((i, i + 1), (x, y))
    ans[i + 1] = ((i, i + 1), (x, y))
    pos[x].append(i)
    pos[y].append(i)

# x at (i or i2) and j
def solve_triple(i, i2, j):
    assert isinstance(ans[i], tuple)
    assert isinstance(ans[j], int)
    x = ans[j]
    y = sum(ans[i][1]) - x

    pos[y].remove(min(i, i2))

    while True:
        a, b = query(i, j)
        if a == b:
            break
        j, i2 = i2, j

    ans[i] = ans[j] = x
    ans[i2] = y
    pos[x] = [i, j]
    pos[y].append(i2)


# Resolve all pairs
i = 0
swapped = False
extra_pair = None
while i < n:
    if isinstance(ans[i], int) or (extra_pair and i in extra_pair):
        i += 1
        continue

    x, y = ans[i][1]
    i2 = sum(ans[i][0]) - i
    # Find other pair of x
    pp = None
    for p in pos[x]:
        if p != min(i, i2):
            pp = p
            break

    assert pp is not None
    if isinstance(ans[pp], int):
        if swapped:
            if extra_pair is None:
                extra_pair = (i, i2)
            else:
                # Mix the current pair with the disjoint extra_pair.
                j, j2 = extra_pair
                u, v = ans[j][1]
                extra_pair = (i, j)
                a1, a2 = query(i, j)
                if a1 not in [x, y]:
                    a1, a2 = a2, a1
                assert a1 in [x, y]
                assert a2 in [u, v]
                ans[i2] = x + y - a1
                ans[j2] = u + v - a2
                ans[i] = ((i, j), (a1, a2))
                ans[j] = ((i, j), (a1, a2))
                pos[x].remove(min(i, i2))
                pos[y].remove(min(i, i2))
                pos[u].remove(min(j, j2))
                pos[v].remove(min(j, j2))
                pos[x + y - a1].append(i2)
                pos[u + v - a2].append(j2)
                pos[a1].append(min(i, j))
                pos[a2].append(min(i, j))

            i += 1
            swapped = False
        else:
            ans[i] = (ans[i][0], (y, x))
            swapped = True
        continue
    swapped = False
    assert i2 > i

    pp = ans[pp][0]
    j = pp[0]
    assert j > i
    j2 = pp[1]
    assert j2 > i
    u, v = ans[j][1]
    assert x == u or x == v
    if x != u:
        u, v = v, u
    # print(f'Pos {ans[i][0]} matches with {pp} with values {x}, {y} and {u}, {v}', file=sys.stderr)

    pos[x].remove(min(i, i2))
    pos[y].remove(min(i, i2))
    pos[u].remove(min(j, j2))
    pos[v].remove(min(j, j2))

    s = {x, y, u, v}
    assert len(s) >= 2 and len(s) < 4
    if len(s) == 2:
        # print('LEN: 2', file=sys.stderr)
        a1, a2 = query(i, j)
        assert a1 in s
        assert a2 in s
        if a1 == a2:
            ans[i] = ans[j] = a1
            ans[i2] = ans[j2] = x + y - a1
            pos[a1] = [i, j]
            pos[x + y - a1] = [i2, j2]
        else:
            ans[i] = ((i, j), (a1, a2))
            ans[j] = ((i, j), (a1, a2))
            ans[i2] = ((i2, j2), (a1, a2))
            ans[j2] = ((i2, j2), (a1, a2))
            pos[a1] = [min(i, j), min(i2, j2)]
            pos[a2] = [min(i, j), min(i2, j2)]
        continue
    if len(s) == 3:
        a1, a2 = query(i, j)
        assert a1 in s
        assert a2 in s
        if a1 == a2:
            assert a1 == x and a2 == x
            ans[i] = ans[j] = x
            ans[i2] = y
            ans[j2] = v
            pos[x] = [i, j]
            pos[y].append(i2)
            pos[v].append(j2)
        elif a1 != x and a2 != x:
            assert {a1, a2} == {y, v}
            ans[i] = ((i, j), (y, v))
            ans[j] = ((i, j), (y, v))
            ans[i2] = ans[j2] = x
            pos[x] = [i2, j2]
            pos[y].append(min(i, j))
            pos[v].append(min(i, j))
        else:
            # We hit one of the two xs.
            nonx = a2 if a1 == x else a1
            assert nonx in [y, v]
            if nonx == y:
                assert {a1, a2} == {x, y}
                ans[i2] = x
                ans[j2] = v
                ans[i] = ((i, j), (x, y))
                ans[j] = ((i, j), (x, y))

                pos[x] = [min(i, j), i2]
                pos[y].append(min(i, j))
                pos[v].append(j2)
            else:
                assert {a1, a2} == {x, v}
                ans[i2] = y
                ans[j2] = x
                ans[i] = ((i, j), (x, v))
                ans[j] = ((i, j), (x, v))

                pos[x] = [min(i, j), j2]
                pos[y].append(i2)
                pos[v].append(min(i, j))

# Resolve the extra pair.
if extra_pair:
    i, i2 = extra_pair
    x, y = ans[i][1]
    j = None
    for p in pos[x]:
        if p != min(i, i2):
            j = p
            break
    assert j is not None
    solve_triple(i, i2, j)

print("!", *[ans[iperm[i]] for i in range(n)])
