← Home
package main

import (
	"bufio"
	"fmt"
	"math/bits"
	"math/rand"
	"os"
	"time"
)

var (
	in    *bufio.Reader
	out   *bufio.Writer
	n     int
	cache []int16
)

func pos(i, j int) int {
	return i*n + j
}

func ask(i, j int) int {
	if i == j {
		return 0
	}
	p := pos(i, j)
	if cache[p] != -1 {
		return int(cache[p])
	}
	fmt.Fprintf(out, "? %d %d\n", i+1, j+1)
	out.Flush()
	var x int
	fmt.Fscan(in, &x)
	if x < 0 {
		os.Exit(0)
	}
	cache[pos(i, j)] = int16(x)
	cache[pos(j, i)] = int16(x)
	return x
}

func chooseStart() int {
	s := 15
	if n < s {
		s = n
	}
	sample := rand.Perm(n)[:s]
	for i := 0; i < s; i++ {
		for j := i + 1; j < s; j++ {
			ask(sample[i], sample[j])
		}
	}
	best := sample[0]
	bestPop := 1 << 30
	for _, v := range sample {
		mask := 0
		for b := 0; b < 11; b++ {
			bit := 1 << b
			ok := true
			for _, u := range sample {
				if u == v {
					continue
				}
				if ask(v, u)&bit == 0 {
					ok = false
					break
				}
			}
			if ok {
				mask |= bit
			}
		}
		pc := bits.OnesCount(uint(mask))
		if pc < bestPop {
			bestPop = pc
			best = v
		}
	}
	return best
}

func findZero(start int) (int, bool, []int) {
	set := make([]int, n)
	for i := 0; i < n; i++ {
		set[i] = i
	}
	cur := start
	minPos := 1
	for {
		if len(set) == 1 {
			return set[0], false, nil
		}
		mn := 1 << 30
		eq := make([]int, 0)
		ans := make(map[int]int, len(set)-1)
		for _, v := range set {
			if v == cur {
				continue
			}
			x := ask(cur, v)
			ans[v] = x
			if x < mn {
				mn = x
				eq = eq[:0]
				eq = append(eq, v)
			} else if x == mn {
				eq = append(eq, v)
			}
		}
		if mn == minPos {
			other := eq[0]
			zero := other
			for _, v := range set {
				if v == cur || v == other {
					continue
				}
				if ans[v]&minPos == 0 {
					zero = cur
					break
				}
			}
			if zero == cur && len(set) == n {
				p := make([]int, n)
				p[cur] = 0
				for idx, val := range ans {
					p[idx] = val
				}
				return zero, true, p
			}
			return zero, false, nil
		}
		if len(eq) == 1 {
			return eq[0], false, nil
		}
		next := make([]int, len(eq))
		copy(next, eq)
		set = next
		cur = set[rand.Intn(len(set))]
		minPos = mn & -mn
	}
}

func reconstruct(z int) []int {
	p := make([]int, n)
	p[z] = 0
	for i := 0; i < n; i++ {
		if i == z {
			continue
		}
		p[i] = ask(z, i)
	}
	return p
}

func main() {
	in = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
	defer out.Flush()

	fmt.Fscan(in, &n)

	cache = make([]int16, n*n)
	for i := range cache {
		cache[i] = -1
	}

	rand.Seed(time.Now().UnixNano())

	start := chooseStart()
	zero, known, p := findZero(start)
	if !known {
		p = reconstruct(zero)
	}

	fmt.Fprint(out, "!")
	for i := 0; i < n; i++ {
		fmt.Fprintf(out, " %d", p[i])
	}
	fmt.Fprintln(out)
	out.Flush()
}