Problem:
C: 今川焼きマン - Imagawayaki Man -
物語
今川焼きマンは、正義のヒーローである。顔は直径
1
メートルの今川焼き（主に小麦粉でできた生地の中にたっぷりと餡を詰めて焼いた食べ物であり、見た目は円形であり、美味しい。北海道では、単に「お焼き」と呼ばれることも多い。餡として小豆餡のほかに、カスタードクリームなどを用いることもあり、さまざまな味のバリエーションがある。そのため、いくつ食べても飽きない。小豆餡やカスタードクリームのほかに、抹茶餡やりんごジャムなども美味しい。中にタコを入れたたこ焼きのようなものもあるようだ。どの味も美味しい。下の写真は標準的な今川焼きである。左はクリーム餡、右は小豆餡が入っている。美味しそうである。実際に食べて見たところ、やはり美味しかった。ところで、今川焼きの直径は通常
10
センチメートル程度であるので、直径
1
メートルの今川焼きはかなり大きなものであることに注意されよ。）でできており、お腹の空いた者に自分の顔を分けて差し出すこともある。そのため、必要に応じて顔を取り替える必要がある。いつでも取り替えられるように、今川焼き工場でおじさんが一人でせっせと一つずつ今川焼きを焼いて日々備えている。
ところで、今川焼きは食品であるため、当然ながら賞味期限が存在する。無駄にしないためには、焼いてから時間が経ったものから順に使うことが望ましい。おじさんは下図のように、完成した直径
1
メートルの今川焼き (図中の狐色部) を幅
1
メートルのレーン (図中の灰色部) の上に隙間なく並べて保存している。
ある日、大悪党の背筋マンが工場に現れ、今川焼きマンを困らせようと、自慢の背筋力を使って巨大な今川焼きをせっせと運び、好き勝手に並び替えてしまった。背筋マンは背筋力だけでなく記憶力も良いので、どの今川焼きが元々何番目にあったのか覚えているようだ。負けを認めたくない今川焼きマンは、何とかして、それぞれの今川焼きが何番目に出来たてなのか知りたいが、見た目では分かりそうにない。そこで、背筋マンに「もちろん、僕はちゃんと覚えているよ。でも、背筋マンは本当にちゃんと覚えているのかな？？」と挑発し、さらに「本当に覚えているか僕がテストするよ！」と言って質問を繰り返すことで、何番目に出来たてなのか知ることにした。ただし、あまり質問しすぎると、探っていることを勘付かれてしまうので、ほどほどにしなければならない。あなたには、今川焼きマンを助けるため、質問を繰り返し生成し、それぞれの今川焼きが何番目に出来たてなのかを当てるプログラムを作成してほしい。
問題
まず、工場に並んでいる今川焼きの個数
N
(
1 \leq N \leq 10,000
) が標準入力により1行で与えられる。これらの今川焼きの製造日時は互いに異なる。つまり、
1 \leq i \leq N
を満たす任意の整数
i
について、
i
番目に出来たての今川焼きはただひとつ存在する。
これ以降、任意の2整数
a
,
b
(
1 \leq a, b \leq N
) において、標準出力に
?
a
b
と出力すると、「
a
番目に出来たての今川焼きの中心から
b
番目に出来たての今川焼きの中心までの距離は何メートルか？」という質問を行うことができる。この答えは標準入力に一行で整数としてすぐに与えられる。物語でも述べた通り、レーン上に隙間なく直径
1
メートルの今川焼きが並べられているので、左から数えて
i
番目の今川焼きの中心から
j
番目の今川焼きの中心までの距離は正確に
|i - j|
メートルである。この質問は
20,000
回まで繰り返し行うことができる。
それぞれの今川焼きが何番目に出来たてなのか分かったら、標準出力に最終的な答えを出力しなければならない。出力形式は、各
i
(
1 \leq i \leq N
) において、左から
i
番目 の今川焼きが
x_i
番目に出来たてのとき、
!
x_1
x_2
x_3
...
x_N
または、
!
x_N
x_{N-1}
x_{N-2}
...
x_1
とすればよい。つまり、左から順に答えても、右から順に答えても構わない。この最終的な解答は、1度しか行うことができない。この解答が正しい出力だったとき、正答とみなす。
標準出力を行う毎に、ストリームをフラッシュ (flush) する必要があることに注意されよ。主要な言語でのフラッシュ例を以下に示す。もちろん、これ以外の方法でフラッシュを行っても構わない。
C 言語:
#include <stdio.h>
fflush(stdout);
C++:
#include <iostream>
std::cout.flush();
Java:
System.out.flush();
入出力例
標準入力
標準出力
3
? 1 2
2
? 2 3
1
? 1 3
1
! 2 3 1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const ll mod=1e9+7;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}
template<class T> T min(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;}
template<class T> T max(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;}


void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	int N;
	cin>>N;
	vector<int> p(N);
	int ind=0;
	if(N==1){
		cout<<"! 1"<<endl;
		return;
	}
	if(N==2){
		cout<<"! 1 2"<<endl;
		return;
	}
	rep(i,N-1){
		cout<<"? 1 "<<i+2<<endl;
		cin>>p[i+1];
		if(p[i+1]==1){
			ind=i+1;
		}
	}
	vector<int> L,R;
	rep(i,N){
		if(i==0||i==ind) continue;
		cout<<"? "<<ind+1<<" "<<i+1<<endl;
		int tmp;
		cin>>tmp;
		if(tmp<p[i]) L.push_back(i);
		else R.push_back(i);
	}
	sort(all(R),[&](int l,int r){
		return p[l]<p[r];
	});
	sort(all(L),[&](int l,int r){
		return p[l]>p[r];
	});
	cout<<"!";
	for(auto x:L) cout<<" "<<x+1;
	cout<<" "<<ind+1<<" "<<1;
	for(auto x:R) cout<<" "<<x+1;
	cout<<endl;
}
//4 2 3 1 5
accuracy: 1
time_ms: 100
memory_kb: 3876
final_rank: 7

code_snippet: #line 1 "/home/yuruhiya/programming/library/template14.cpp"
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define rrep(i, n) for (int i = (n)-1; i >= 0; --i)
#define rfor(i, m, n) for (int i = (m); i >= (n); --i)
#define unless(c) if (!(c))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define range_it(a, l, r) (a).begin() + (l), (a).begin() + (r)

using namespace std;
using ll = long long;
using LD = long double;
using VB = vector<bool>;
using VVB = vector<VB>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using VS = vector<string>;
using VD = vector<LD>;
using PII = pair<int, int>;
using VP = vector<PII>;
using PLL = pair<ll, ll>;
using VPL = vector<PLL>;
template <class T> using PQ = priority_queue<T>;
template <class T> using PQS = priority_queue<T, vector<T>, greater<T>>;
constexpr int inf = 1e9;
constexpr long long inf_ll = 1e18, MOD = 1000000007;
constexpr long double PI = M_PI, EPS = 1e-12;

// --- input --- //
#ifdef _WIN32
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#define fwrite_unlocked fwrite
#define fflush_unlocked fflush
#endif
class Scanner {
	static int gc() {
		return getchar_unlocked();
	}
	static char next_char() {
		char c;
		read(c);
		return c;
	}
	template <class T> static void read(T& v) {
		cin >> v;
	}
	static void read(char& v) {
		while (isspace(v = gc()))
			;
	}
	static void read(bool& v) {
		v = next_char() != '0';
	}
	static void read(string& v) {
		v.clear();
		for (char c = next_char(); !isspace(c); c = gc()) v += c;
	}
	static void read(int& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(long long& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(double& v) {
		v = 0;
		double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	static void read(long double& v) {
		v = 0;
		long double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	template <class T, class U> static void read(pair<T, U>& v) {
		read(v.first);
		read(v.second);
	}
	template <class T> static void read(vector<T>& v) {
		for (auto& e : v) read(e);
	}
	struct ReadVectorHelper {
		size_t n;
		ReadVectorHelper(size_t _n) : n(_n) {}
		template <class T> operator vector<T>() {
			vector<T> v(n);
			read(v);
			return v;
		}
	};
	struct Read2DVectorHelper {
		size_t n, m;
		Read2DVectorHelper(const pair<size_t, size_t>& nm) : n(nm.first), m(nm.second) {}
		template <class T> operator vector<vector<T>>() {
			vector<vector<T>> v(n, vector<T>(m));
			read(v);
			return v;
		}
	};

public:
	string read_line() const {
		string v;
		for (char c = gc(); c != '\n' && c != '\0'; c = gc()) v += c;
		return v;
	}
	template <class T> T read() const {
		T v;
		read(v);
		return v;
	}
	template <class T> vector<T> read_vector(size_t n) const {
		vector<T> a(n);
		read(a);
		return a;
	}
	template <class T> operator T() const {
		return read<T>();
	}
	int operator--(int) const {
		return read<int>() - 1;
	}
	ReadVectorHelper operator[](size_t n) const {
		return ReadVectorHelper(n);
	}
	Read2DVectorHelper operator[](const pair<size_t, size_t>& nm) const {
		return Read2DVectorHelper(nm);
	}
	void operator()() const {}
	template <class H, class... T> void operator()(H&& h, T&&... t) const {
		read(h);
		operator()(forward<T>(t)...);
	}
} in;
#define inputs(T, ...) \
	T __VA_ARGS__;     \
	in(__VA_ARGS__)
#define ini(...) inputs(int, __VA_ARGS__)
#define inl(...) inputs(long long, __VA_ARGS__)
#define ins(...) inputs(string, __VA_ARGS__)

// --- output --- //
struct BoolStr {
	const char *t, *f;
	BoolStr(const char* _t, const char* _f) : t(_t), f(_f) {}
} Yes("Yes", "No"), yes("yes", "no"), YES("YES", "NO"), Int("1", "0");
struct DivStr {
	const char *d, *l;
	DivStr(const char* _d, const char* _l) : d(_d), l(_l) {}
} spc(" ", "\n"), no_spc("", "\n"), end_line("\n", "\n"), comma(",", "\n"),
    no_endl(" ", "");
class Printer {
	BoolStr B{Yes};
	DivStr D{spc};

public:
	void print(int v) const {
		if (v < 0) putchar_unlocked('-'), v = -v;
		char b[10];
		int i = 0;
		while (v) b[i++] = '0' + v % 10, v /= 10;
		if (!i) b[i++] = '0';
		while (i--) putchar_unlocked(b[i]);
	}
	void print(long long v) const {
		if (v < 0) putchar_unlocked('-'), v = -v;
		char b[20];
		int i = 0;
		while (v) b[i++] = '0' + v % 10, v /= 10;
		if (!i) b[i++] = '0';
		while (i--) putchar_unlocked(b[i]);
	}
	void print(bool v) const {
		print(v ? B.t : B.f);
	}
	void print(vector<bool>::reference v) const {
		print(v ? B.t : B.f);
	}
	void print(char v) const {
		putchar_unlocked(v);
	}
	void print(const char* v) const {
		fwrite_unlocked(v, 1, strlen(v), stdout);
	}
	void print(double v) const {
		printf("%.20f", v);
	}
	void print(long double v) const {
		printf("%.20Lf", v);
	}
	template <class T> void print(const T& v) const {
		cout << v;
	}
	template <class T, class U> void print(const pair<T, U>& v) const {
		print(v.first);
		print(D.d);
		print(v.second);
	}
	template <class InputIterater>
	void print_range(const InputIterater& begin, const InputIterater& end) const {
		for (InputIterater i = begin; i != end; ++i) {
			if (i != begin) print(D.d);
			print(*i);
		}
	}
	template <class T> void print(const vector<T>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T, size_t N> void print(const array<T, N>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T> void print(const vector<vector<T>>& v) const {
		for (size_t i = 0; i < v.size(); ++i) {
			if (i) print(D.l);
			print(v[i]);
		}
	}

	Printer() = default;
	Printer(const BoolStr& _boolstr, const DivStr& _divstr) : B(_boolstr), D(_divstr) {}
	Printer& operator()() {
		print(D.l);
		return *this;
	}
	template <class H> Printer& operator()(H&& h) {
		print(h);
		print(D.l);
		return *this;
	}
	template <class H, class... T> Printer& operator()(H&& h, T&&... t) {
		print(h);
		print(D.d);
		return operator()(forward<T>(t)...);
	}
	template <class InputIterator>
	Printer& range(const InputIterator& begin, const InputIterator& end) {
		print_range(begin, end);
		print(D.l);
		return *this;
	}
	template <class T> Printer& range(const T& a) {
		range(a.begin(), a.end());
		return *this;
	}
	template <class... T> void exit(T&&... t) {
		operator()(forward<T>(t)...);
		std::exit(EXIT_SUCCESS);
	}
	Printer& flush() {
		fflush_unlocked(stdout);
		return *this;
	}
	Printer& set(const BoolStr& b) {
		B = b;
		return *this;
	}
	Printer& set(const DivStr& d) {
		D = d;
		return *this;
	}
	Printer& set(const char* t, const char* f) {
		B = BoolStr(t, f);
		return *this;
	}
} out;

// --- step --- //
template <class T> struct Step {
	class It {
		T a, b, c;

	public:
		constexpr It() : a(T()), b(T()), c(T()) {}
		constexpr It(T _b, T _c, T _s) : a(_b), b(_c), c(_s) {}
		constexpr It& operator++() {
			--b;
			a += c;
			return *this;
		}
		constexpr It operator++(int) {
			It tmp = *this;
			--b;
			a += c;
			return tmp;
		}
		constexpr const T& operator*() const {
			return a;
		}
		constexpr const T* operator->() const {
			return &a;
		}
		constexpr bool operator==(const It& i) const {
			return b == i.b;
		}
		constexpr bool operator!=(const It& i) const {
			return !(b == i.b);
		}
		constexpr T start() const {
			return a;
		}
		constexpr T count() const {
			return b;
		}
		constexpr T step() const {
			return c;
		}
	};
	constexpr Step(T b, T c, T s) : be(b, c, s) {}
	constexpr It begin() const {
		return be;
	}
	constexpr It end() const {
		return en;
	}
	constexpr T start() const {
		return be.start();
	}
	constexpr T count() const {
		return be.count();
	}
	constexpr T step() const {
		return be.step();
	}
	constexpr T sum() const {
		return start() * count() + step() * (count() * (count() - 1) / 2);
	}
	operator vector<T>() const {
		return to_a();
	}
	template <class F> void each(const F& f) const {
		for (T i : *this) f(i);
	}
	auto to_a() const {
		vector<T> res;
		res.reserve(count());
		each([&](T i) { res.push_back(i); });
		return res;
	}
	template <class F, class U = decay_t<result_of_t<F(T)>>> auto map(const F& f) const {
		vector<U> res;
		res.reserve(count());
		each([&](T i) { res.push_back(f(i)); });
		return res;
	}
	template <class F> auto select(const F& f) const {
		vector<T> res;
		each([&](T i) {
			if (f(i)) res.push_back(i);
		});
		return res;
	}
	template <class F> int count_if(const F& f) const {
		int res = 0;
		each([&](T i) {
			if (f(i)) ++res;
		});
		return res;
	}
	template <class F> T find_if(const F& f) const {
		for (T i : *this)
			if (f(i)) return i;
		return 0;
	}
	template <class F> auto max_by(const F& f) const {
		auto v = map(f);
		return *max_element(v.begin(), v.end());
	}
	template <class F> auto min_by(const F& f) const {
		auto v = map(f);
		return *min_element(v.begin(), v.end());
	}
	template <class F> bool all_of(const F& f) const {
		for (T i : *this)
			if (!f(i)) return false;
		return true;
	}
	template <class F> bool any_of(const F& f) const {
		for (T i : *this)
			if (f(i)) return true;
		return false;
	}
	template <class F, class U = decay_t<result_of_t<F(T)>>> auto sum(const F& f) const {
		U res = 0;
		each([&](T i) { res += static_cast<U>(f(i)); });
		return res;
	}
	using value_type = T;
	using iterator = It;

private:
	It be, en;
};
template <class T> constexpr auto step(T a) {
	return Step<T>(0, a, 1);
}
template <class T> constexpr auto step(T a, T b) {
	return Step<T>(a, b - a, 1);
}
template <class T> constexpr auto step(T a, T b, T c) {
	return Step<T>(a, a < b ? (b - a - 1) / c + 1 : 0, c);
}

// --- functions --- //
inline namespace {
	template <class T> void Sort(T& a) {
		sort(all(a));
	}
	template <class T> void RSort(T& a) {
		sort(rall(a));
	}
	template <class T, class F> void Sort(T& a, const F& f) {
		sort(all(a), f);
	}
	template <class T, class F> void RSort(T& a, const F& f) {
		sort(rall(a), f);
	}
	template <class T> T Sorted(T a) {
		Sort(a);
		return a;
	}
	template <class T> T RSorted(T a) {
		RSort(a);
		return a;
	}
	template <class T, class F> T Sorted(T& a, const F& f) {
		Sort(a, f);
		return a;
	}
	template <class T, class F> T RSorted(T& a, const F& f) {
		RSort(a, f);
		return a;
	}
	template <class T, class F> void SortBy(T& a, const F& f) {
		sort(all(a), [&](const auto& x, const auto& y) { return f(x) < f(y); });
	}
	template <class T, class F> void RSortBy(T& a, const F& f) {
		sort(rall(a), [&](const auto& x, const auto& y) { return f(x) < f(y); });
	}
	template <class T> void Reverse(T& a) {
		reverse(all(a));
	}
	template <class T> void Unique(T& a) {
		a.erase(unique(all(a)), a.end());
	}
	template <class T> void Uniq(T& a) {
		Sort(a);
		Unique(a);
	}
	template <class T> void Rotate(T& a, int left) {
		rotate(a.begin(), a.begin() + left, a.end());
	}
	template <class T> T Reversed(T a) {
		Reverse(a);
		return a;
	}
	template <class T> T Uniqued(T a) {
		Unique(a);
		return a;
	}
	template <class T> T Uniqed(T a) {
		Uniq(a);
		return a;
	}
	template <class T> T Rotated(T a, int left) {
		Rotate(a, left);
		return a;
	}
	template <class T> auto Max(const T& a) {
		return *max_element(all(a));
	}
	template <class T> auto Min(const T& a) {
		return *min_element(all(a));
	}
	template <class T> int MaxPos(const T& a) {
		return max_element(all(a)) - a.begin();
	}
	template <class T> int MinPos(const T& a) {
		return min_element(all(a)) - a.begin();
	}
	template <class T, class F> auto MaxBy(const T& a, const F& f) {
		return *max_element(all(a),
		                    [&](const auto& x, const auto& y) { return f(x) < f(y); });
	}
	template <class T, class F> auto MinBy(const T& a, const F& f) {
		return *min_element(all(a),
		                    [&](const auto& x, const auto& y) { return f(x) < f(y); });
	}
	template <class T, class F> auto MaxOf(const T& a, const F& f) {
		return Max(Map(a, f));
	}
	template <class T, class F> auto MinOf(const T& a, const F& f) {
		return Min(Map(a, f));
	}
	template <class T, class U> int Count(const T& a, const U& v) {
		return count(all(a), v);
	}
	template <class T, class F> int CountIf(const T& a, const F& f) {
		return count_if(all(a), f);
	}
	template <class T, class U> int Find(const T& a, const U& v) {
		return find(all(a), v) - a.begin();
	}
	template <class T, class F> int FindIf(const T& a, const F& f) {
		return find_if(all(a), f) - a.begin();
	}
	template <class T, class U = typename T::value_type> U Sum(const T& a) {
		return accumulate(all(a), U());
	}
	template <class T, class U> bool Includes(const T& a, const U& v) {
		return find(all(a), v) != a.end();
	}
	template <class T, class F> auto Sum(const T& v, const F& f) {
		return accumulate(next(v.begin()), v.end(), f(*v.begin()),
		                  [&](auto a, auto b) { return a + f(b); });
	}
	template <class T, class U> int Lower(const T& a, const U& v) {
		return lower_bound(all(a), v) - a.begin();
	}
	template <class T, class U> int Upper(const T& a, const U& v) {
		return upper_bound(all(a), v) - a.begin();
	}
	template <class T, class F> void RemoveIf(T& a, const F& f) {
		a.erase(remove_if(all(a), f), a.end());
	}
	template <class F> auto Vector(size_t size, const F& f) {
		vector<decay_t<result_of_t<F(size_t)>>> res(size);
		for (size_t i = 0; i < size; ++i) res[i] = f(i);
		return res;
	}
	template <class T> auto Grid(size_t h, size_t w, const T& v = T()) {
		return vector<vector<T>>(h, vector<T>(w, v));
	}
	template <class T> auto Slice(const T& v, size_t i, size_t len) {
		return i < v.size() ? T(v.begin() + i, v.begin() + min(i + len, v.size())) : T();
	}
	template <class T, class F> auto Each(const T& v, F&& f) {
		for (auto& i : v) f(i);
	}
	template <class T, class F> auto Select(const T& v, const F& f) {
		T res;
		for (const auto& e : v)
			if (f(e)) res.push_back(e);
		return res;
	}
	template <class T, class F> auto Map(const T& v, F&& f) {
		vector<decay_t<result_of_t<F(typename T::value_type)>>> res(v.size());
		size_t i = 0;
		for (const auto& e : v) res[i++] = f(e);
		return res;
	}
	template <class T, class F> auto MapIndex(const T& v, const F& f) {
		vector<decay_t<result_of_t<F(size_t, typename T::value_type)>>> res(v.size());
		size_t i = 0;
		for (auto it = v.begin(); it != v.end(); ++it, ++i) res[i] = f(i, *it);
		return res;
	}
	template <class T, class F> auto TrueIndex(const T& v, const F& f) {
		vector<size_t> res;
		for (size_t i = 0; i < v.size(); ++i)
			if (f(v[i])) res.push_back(i);
		return res;
	}
	template <class T, class U = typename T::value_type> auto Indexed(const T& v) {
		vector<pair<U, int>> res(v.size());
		for (int i = 0; i < (int)v.size(); ++i)
			res[i] = make_pair(static_cast<U>(v[i]), i);
		return res;
	}
	auto operator*(string s, size_t n) {
		string res;
		for (size_t i = 0; i < n; ++i) res += s;
		return res;
	}
	template <class T> auto& operator<<(vector<T>& v, const vector<T>& v2) {
		v.insert(v.end(), all(v2));
		return v;
	}
	template <class T> T Ceil(T n, T m) {
		return (n + m - 1) / m;
	}
	template <class T> T Ceil2(T n, T m) {
		return Ceil(n, m) * m;
	}
	template <class T> T Tri(T n) {
		return (n & 1) ? (n + 1) / 2 * n : n / 2 * (n + 1);
	}
	template <class T> T nC2(T n) {
		return (n & 1) ? (n - 1) / 2 * n : n / 2 * (n - 1);
	}
	template <class T> T Mid(const T& l, const T& r) {
		return l + (r - l) / 2;
	}
	template <class T> bool chmax(T& a, const T& b) {
		if (a < b) {
			a = b;
			return true;
		}
		return false;
	}
	template <class T> bool chmin(T& a, const T& b) {
		if (a > b) {
			a = b;
			return true;
		}
		return false;
	}
	template <class T> bool inRange(const T& v, const T& min, const T& max) {
		return min <= v && v < max;
	}
	template <class T> bool isSquere(T n) {
		T s = sqrt(n);
		return s * s == n || (s + 1) * (s + 1) == n;
	}
	template <class T = long long> T BIT(int b) {
		return T(1) << b;
	}
	template <class T> T Gcd(T n, T m) {
		return m ? Gcd(m, n % m) : n;
	}
	template <class T> T Lcm(T n, T m) {
		return n / Gcd(n, m) * m;
	}
	template <class T, class U = typename T::value_type> U Gcdv(const T& v) {
		return accumulate(next(v.begin()), v.end(), U(*v.begin()), Gcd<U>);
	}
	template <class T, class U = typename T::value_type> U Lcmv(const T& v) {
		return accumulate(next(v.begin()), v.end(), U(*v.begin()), Lcm<U>);
	}
	template <class T> T Pow(T a, T n) {
		T r = 1;
		while (n > 0) {
			if (n & 1) r *= a;
			a *= a;
			n /= 2;
		}
		return r;
	}
	template <class T> T Powmod(T a, T n, T m = MOD) {
		T r = 1;
		while (n > 0) {
			if (n & 1)
				r = r * a % m, n--;
			else
				a = a * a % m, n /= 2;
		}
		return r;
	}
}  // namespace

// --- dump --- //
#if __has_include(<library/dump.hpp>)
#include <library/dump.hpp>
#else
#define dump(...) ((void)0)
#endif

// ---------------------------------------------------------------- //
#line 2 "a.cpp"

int ask(int i, int j) {
	out('?', i + 1, j + 1).flush();
	return in.read<int>();
}

int main() {
	ini(n);
	if (n == 1) {
		out.exit('!', 1);
	}
	VVI dist(n + 1);
	FOR(i, 1, n) dist[ask(0, i)].push_back(i);

	deque<int> ans;
	ans.push_back(0);
	ans.push_back(dist[1][0]);
	if (dist[1].size() == 2) {
		ans.push_front(dist[1][1]);
	}
	FOR(i, 2, n + 1) {
		if (dist[i].empty()) break;
		if (ask(dist[i][0], ans.back()) == 1) {
			ans.push_back(dist[i][0]);
			if (dist[i].size() == 2) {
				ans.push_front(dist[i][1]);
			}
		} else {
			ans.push_front(dist[i][0]);
			if (dist[i].size() == 2) {
				ans.push_back(dist[i][1]);
			}
		}
	}

	VI a(n);
	rep(i, n) a[i] = ans[i] + 1;
	out('!', a);
}
accuracy: 1
time_ms: 130
memory_kb: 3676
final_rank: 2

code_snippet: #line 1 "/home/yuruhiya/programming/library/template14.cpp"
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define rrep(i, n) for (int i = (n)-1; i >= 0; --i)
#define rfor(i, m, n) for (int i = (m); i >= (n); --i)
#define unless(c) if (!(c))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define range_it(a, l, r) (a).begin() + (l), (a).begin() + (r)

using namespace std;
using ll = long long;
using LD = long double;
using VB = vector<bool>;
using VVB = vector<VB>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using VS = vector<string>;
using VD = vector<LD>;
using PII = pair<int, int>;
using VP = vector<PII>;
using PLL = pair<ll, ll>;
using VPL = vector<PLL>;
template <class T> using PQ = priority_queue<T>;
template <class T> using PQS = priority_queue<T, vector<T>, greater<T>>;
constexpr int inf = 1e9;
constexpr long long inf_ll = 1e18, MOD = 1000000007;
constexpr long double PI = M_PI, EPS = 1e-12;

// --- input --- //
#ifdef _WIN32
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#define fwrite_unlocked fwrite
#define fflush_unlocked fflush
#endif
class Scanner {
	static int gc() {
		return getchar_unlocked();
	}
	static char next_char() {
		char c;
		read(c);
		return c;
	}
	template <class T> static void read(T& v) {
		cin >> v;
	}
	static void read(char& v) {
		while (isspace(v = gc()))
			;
	}
	static void read(bool& v) {
		v = next_char() != '0';
	}
	static void read(string& v) {
		v.clear();
		for (char c = next_char(); !isspace(c); c = gc()) v += c;
	}
	static void read(int& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(long long& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(double& v) {
		v = 0;
		double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	static void read(long double& v) {
		v = 0;
		long double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	template <class T, class U> static void read(pair<T, U>& v) {
		read(v.first);
		read(v.second);
	}
	template <class T> static void read(vector<T>& v) {
		for (auto& e : v) read(e);
	}
	struct ReadVectorHelper {
		size_t n;
		ReadVectorHelper(size_t _n) : n(_n) {}
		template <class T> operator vector<T>() {
			vector<T> v(n);
			read(v);
			return v;
		}
	};
	struct Read2DVectorHelper {
		size_t n, m;
		Read2DVectorHelper(const pair<size_t, size_t>& nm) : n(nm.first), m(nm.second) {}
		template <class T> operator vector<vector<T>>() {
			vector<vector<T>> v(n, vector<T>(m));
			read(v);
			return v;
		}
	};

public:
	string read_line() const {
		string v;
		for (char c = gc(); c != '\n' && c != '\0'; c = gc()) v += c;
		return v;
	}
	template <class T> T read() const {
		T v;
		read(v);
		return v;
	}
	template <class T> vector<T> read_vector(size_t n) const {
		vector<T> a(n);
		read(a);
		return a;
	}
	template <class T> operator T() const {
		return read<T>();
	}
	int operator--(int) const {
		return read<int>() - 1;
	}
	ReadVectorHelper operator[](size_t n) const {
		return ReadVectorHelper(n);
	}
	Read2DVectorHelper operator[](const pair<size_t, size_t>& nm) const {
		return Read2DVectorHelper(nm);
	}
	void operator()() const {}
	template <class H, class... T> void operator()(H&& h, T&&... t) const {
		read(h);
		operator()(forward<T>(t)...);
	}
} in;
#define inputs(T, ...) \
	T __VA_ARGS__;     \
	in(__VA_ARGS__)
#define ini(...) inputs(int, __VA_ARGS__)
#define inl(...) inputs(long long, __VA_ARGS__)
#define ins(...) inputs(string, __VA_ARGS__)

// --- output --- //
struct BoolStr {
	const char *t, *f;
	BoolStr(const char* _t, const char* _f) : t(_t), f(_f) {}
} Yes("Yes", "No"), yes("yes", "no"), YES("YES", "NO"), Int("1", "0");
struct DivStr {
	const char *d, *l;
	DivStr(const char* _d, const char* _l) : d(_d), l(_l) {}
} spc(" ", "\n"), no_spc("", "\n"), end_line("\n", "\n"), comma(",", "\n"),
    no_endl(" ", "");
class Printer {
	BoolStr B{Yes};
	DivStr D{spc};

public:
	void print(int v) const {
		if (v < 0) putchar_unlocked('-'), v = -v;
		char b[10];
		int i = 0;
		while (v) b[i++] = '0' + v % 10, v /= 10;
		if (!i) b[i++] = '0';
		while (i--) putchar_unlocked(b[i]);
	}
	void print(long long v) const {
		if (v < 0) putchar_unlocked('-'), v = -v;
		char b[20];
		int i = 0;
		while (v) b[i++] = '0' + v % 10, v /= 10;
		if (!i) b[i++] = '0';
		while (i--) putchar_unlocked(b[i]);
	}
	void print(bool v) const {
		print(v ? B.t : B.f);
	}
	void print(vector<bool>::reference v) const {
		print(v ? B.t : B.f);
	}
	void print(char v) const {
		putchar_unlocked(v);
	}
	void print(const char* v) const {
		fwrite_unlocked(v, 1, strlen(v), stdout);
	}
	void print(double v) const {
		printf("%.20f", v);
	}
	void print(long double v) const {
		printf("%.20Lf", v);
	}
	template <class T> void print(const T& v) const {
		cout << v;
	}
	template <class T, class U> void print(const pair<T, U>& v) const {
		print(v.first);
		print(D.d);
		print(v.second);
	}
	template <class InputIterater>
	void print_range(const InputIterater& begin, const InputIterater& end) const {
		for (InputIterater i = begin; i != end; ++i) {
			if (i != begin) print(D.d);
			print(*i);
		}
	}
	template <class T> void print(const vector<T>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T, size_t N> void print(const array<T, N>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T> void print(const vector<vector<T>>& v) const {
		for (size_t i = 0; i < v.size(); ++i) {
			if (i) print(D.l);
			print(v[i]);
		}
	}

	Printer() = default;
	Printer(const BoolStr& _boolstr, const DivStr& _divstr) : B(_boolstr), D(_divstr) {}
	Printer& operator()() {
		print(D.l);
		return *this;
	}
	template <class H> Printer& operator()(H&& h) {
		print(h);
		print(D.l);
		return *this;
	}
	template <class H, class... T> Printer& operator()(H&& h, T&&... t) {
		print(h);
		print(D.d);
		return operator()(forward<T>(t)...);
	}
	template <class InputIterator>
	Printer& range(const InputIterator& begin, const InputIterator& end) {
		print_range(begin, end);
		print(D.l);
		return *this;
	}
	template <class T> Printer& range(const T& a) {
		range(a.begin(), a.end());
		return *this;
	}
	template <class... T> void exit(T&&... t) {
		operator()(forward<T>(t)...);
		std::exit(EXIT_SUCCESS);
	}
	Printer& flush() {
		fflush_unlocked(stdout);
		return *this;
	}
	Printer& set(const BoolStr& b) {
		B = b;
		return *this;
	}
	Printer& set(const DivStr& d) {
		D = d;
		return *this;
	}
	Printer& set(const char* t, const char* f) {
		B = BoolStr(t, f);
		return *this;
	}
} out;

// --- step --- //
template <class T> struct Step {
	class It {
		T a, b, c;

	public:
		constexpr It() : a(T()), b(T()), c(T()) {}
		constexpr It(T _b, T _c, T _s) : a(_b), b(_c), c(_s) {}
		constexpr It& operator++() {
			--b;
			a += c;
			return *this;
		}
		constexpr It operator++(int) {
			It tmp = *this;
			--b;
			a += c;
			return tmp;
		}
		constexpr const T& operator*() const {
			return a;
		}
		constexpr const T* operator->() const {
			return &a;
		}
		constexpr bool operator==(const It& i) const {
			return b == i.b;
		}
		constexpr bool operator!=(const It& i) const {
			return !(b == i.b);
		}
		constexpr T start() const {
			return a;
		}
		constexpr T count() const {
			return b;
		}
		constexpr T step() const {
			return c;
		}
	};
	constexpr Step(T b, T c, T s) : be(b, c, s) {}
	constexpr It begin() const {
		return be;
	}
	constexpr It end() const {
		return en;
	}
	constexpr T start() const {
		return be.start();
	}
	constexpr T count() const {
		return be.count();
	}
	constexpr T step() const {
		return be.step();
	}
	constexpr T sum() const {
		return start() * count() + step() * (count() * (count() - 1) / 2);
	}
	operator vector<T>() const {
		return to_a();
	}
	template <class F> void each(const F& f) const {
		for (T i : *this) f(i);
	}
	auto to_a() const {
		vector<T> res;
		res.reserve(count());
		each([&](T i) { res.push_back(i); });
		return res;
	}
	template <class F, class U = decay_t<result_of_t<F(T)>>> auto map(const F& f) const {
		vector<U> res;
		res.reserve(count());
		each([&](T i) { res.push_back(f(i)); });
		return res;
	}
	template <class F> auto select(const F& f) const {
		vector<T> res;
		each([&](T i) {
			if (f(i)) res.push_back(i);
		});
		return res;
	}
	template <class F> int count_if(const F& f) const {
		int res = 0;
		each([&](T i) {
			if (f(i)) ++res;
		});
		return res;
	}
	template <class F> T find_if(const F& f) const {
		for (T i : *this)
			if (f(i)) return i;
		return 0;
	}
	template <class F> auto max_by(const F& f) const {
		auto v = map(f);
		return *max_element(v.begin(), v.end());
	}
	template <class F> auto min_by(const F& f) const {
		auto v = map(f);
		return *min_element(v.begin(), v.end());
	}
	template <class F> bool all_of(const F& f) const {
		for (T i : *this)
			if (!f(i)) return false;
		return true;
	}
	template <class F> bool any_of(const F& f) const {
		for (T i : *this)
			if (f(i)) return true;
		return false;
	}
	template <class F, class U = decay_t<result_of_t<F(T)>>> auto sum(const F& f) const {
		U res = 0;
		each([&](T i) { res += static_cast<U>(f(i)); });
		return res;
	}
	using value_type = T;
	using iterator = It;

private:
	It be, en;
};
template <class T> constexpr auto step(T a) {
	return Step<T>(0, a, 1);
}
template <class T> constexpr auto step(T a, T b) {
	return Step<T>(a, b - a, 1);
}
template <class T> constexpr auto step(T a, T b, T c) {
	return Step<T>(a, a < b ? (b - a - 1) / c + 1 : 0, c);
}

// --- functions --- //
inline namespace {
	template <class T> void Sort(T& a) {
		sort(all(a));
	}
	template <class T> void RSort(T& a) {
		sort(rall(a));
	}
	template <class T, class F> void Sort(T& a, const F& f) {
		sort(all(a), f);
	}
	template <class T, class F> void RSort(T& a, const F& f) {
		sort(rall(a), f);
	}
	template <class T> T Sorted(T a) {
		Sort(a);
		return a;
	}
	template <class T> T RSorted(T a) {
		RSort(a);
		return a;
	}
	template <class T, class F> T Sorted(T& a, const F& f) {
		Sort(a, f);
		return a;
	}
	template <class T, class F> T RSorted(T& a, const F& f) {
		RSort(a, f);
		return a;
	}
	template <class T, class F> void SortBy(T& a, const F& f) {
		sort(all(a), [&](const auto& x, const auto& y) { return f(x) < f(y); });
	}
	template <class T, class F> void RSortBy(T& a, const F& f) {
		sort(rall(a), [&](const auto& x, const auto& y) { return f(x) < f(y); });
	}
	template <class T> void Reverse(T& a) {
		reverse(all(a));
	}
	template <class T> void Unique(T& a) {
		a.erase(unique(all(a)), a.end());
	}
	template <class T> void Uniq(T& a) {
		Sort(a);
		Unique(a);
	}
	template <class T> void Rotate(T& a, int left) {
		rotate(a.begin(), a.begin() + left, a.end());
	}
	template <class T> T Reversed(T a) {
		Reverse(a);
		return a;
	}
	template <class T> T Uniqued(T a) {
		Unique(a);
		return a;
	}
	template <class T> T Uniqed(T a) {
		Uniq(a);
		return a;
	}
	template <class T> T Rotated(T a, int left) {
		Rotate(a, left);
		return a;
	}
	template <class T> auto Max(const T& a) {
		return *max_element(all(a));
	}
	template <class T> auto Min(const T& a) {
		return *min_element(all(a));
	}
	template <class T> int MaxPos(const T& a) {
		return max_element(all(a)) - a.begin();
	}
	template <class T> int MinPos(const T& a) {
		return min_element(all(a)) - a.begin();
	}
	template <class T, class F> auto MaxBy(const T& a, const F& f) {
		return *max_element(all(a),
		                    [&](const auto& x, const auto& y) { return f(x) < f(y); });
	}
	template <class T, class F> auto MinBy(const T& a, const F& f) {
		return *min_element(all(a),
		                    [&](const auto& x, const auto& y) { return f(x) < f(y); });
	}
	template <class T, class F> auto MaxOf(const T& a, const F& f) {
		return Max(Map(a, f));
	}
	template <class T, class F> auto MinOf(const T& a, const F& f) {
		return Min(Map(a, f));
	}
	template <class T, class U> int Count(const T& a, const U& v) {
		return count(all(a), v);
	}
	template <class T, class F> int CountIf(const T& a, const F& f) {
		return count_if(all(a), f);
	}
	template <class T, class U> int Find(const T& a, const U& v) {
		return find(all(a), v) - a.begin();
	}
	template <class T, class F> int FindIf(const T& a, const F& f) {
		return find_if(all(a), f) - a.begin();
	}
	template <class T, class U = typename T::value_type> U Sum(const T& a) {
		return accumulate(all(a), U());
	}
	template <class T, class U> bool Includes(const T& a, const U& v) {
		return find(all(a), v) != a.end();
	}
	template <class T, class F> auto Sum(const T& v, const F& f) {
		return accumulate(next(v.begin()), v.end(), f(*v.begin()),
		                  [&](auto a, auto b) { return a + f(b); });
	}
	template <class T, class U> int Lower(const T& a, const U& v) {
		return lower_bound(all(a), v) - a.begin();
	}
	template <class T, class U> int Upper(const T& a, const U& v) {
		return upper_bound(all(a), v) - a.begin();
	}
	template <class T, class F> void RemoveIf(T& a, const F& f) {
		a.erase(remove_if(all(a), f), a.end());
	}
	template <class F> auto Vector(size_t size, const F& f) {
		vector<decay_t<result_of_t<F(size_t)>>> res(size);
		for (size_t i = 0; i < size; ++i) res[i] = f(i);
		return res;
	}
	template <class T> auto Grid(size_t h, size_t w, const T& v = T()) {
		return vector<vector<T>>(h, vector<T>(w, v));
	}
	template <class T> auto Slice(const T& v, size_t i, size_t len) {
		return i < v.size() ? T(v.begin() + i, v.begin() + min(i + len, v.size())) : T();
	}
	template <class T, class F> auto Each(const T& v, F&& f) {
		for (auto& i : v) f(i);
	}
	template <class T, class F> auto Select(const T& v, const F& f) {
		T res;
		for (const auto& e : v)
			if (f(e)) res.push_back(e);
		return res;
	}
	template <class T, class F> auto Map(const T& v, F&& f) {
		vector<decay_t<result_of_t<F(typename T::value_type)>>> res(v.size());
		size_t i = 0;
		for (const auto& e : v) res[i++] = f(e);
		return res;
	}
	template <class T, class F> auto MapIndex(const T& v, const F& f) {
		vector<decay_t<result_of_t<F(size_t, typename T::value_type)>>> res(v.size());
		size_t i = 0;
		for (auto it = v.begin(); it != v.end(); ++it, ++i) res[i] = f(i, *it);
		return res;
	}
	template <class T, class F> auto TrueIndex(const T& v, const F& f) {
		vector<size_t> res;
		for (size_t i = 0; i < v.size(); ++i)
			if (f(v[i])) res.push_back(i);
		return res;
	}
	template <class T, class U = typename T::value_type> auto Indexed(const T& v) {
		vector<pair<U, int>> res(v.size());
		for (int i = 0; i < (int)v.size(); ++i)
			res[i] = make_pair(static_cast<U>(v[i]), i);
		return res;
	}
	auto operator*(string s, size_t n) {
		string res;
		for (size_t i = 0; i < n; ++i) res += s;
		return res;
	}
	template <class T> auto& operator<<(vector<T>& v, const vector<T>& v2) {
		v.insert(v.end(), all(v2));
		return v;
	}
	template <class T> T Ceil(T n, T m) {
		return (n + m - 1) / m;
	}
	template <class T> T Ceil2(T n, T m) {
		return Ceil(n, m) * m;
	}
	template <class T> T Tri(T n) {
		return (n & 1) ? (n + 1) / 2 * n : n / 2 * (n + 1);
	}
	template <class T> T nC2(T n) {
		return (n & 1) ? (n - 1) / 2 * n : n / 2 * (n - 1);
	}
	template <class T> T Mid(const T& l, const T& r) {
		return l + (r - l) / 2;
	}
	template <class T> bool chmax(T& a, const T& b) {
		if (a < b) {
			a = b;
			return true;
		}
		return false;
	}
	template <class T> bool chmin(T& a, const T& b) {
		if (a > b) {
			a = b;
			return true;
		}
		return false;
	}
	template <class T> bool inRange(const T& v, const T& min, const T& max) {
		return min <= v && v < max;
	}
	template <class T> bool isSquere(T n) {
		T s = sqrt(n);
		return s * s == n || (s + 1) * (s + 1) == n;
	}
	template <class T = long long> T BIT(int b) {
		return T(1) << b;
	}
	template <class T> T Gcd(T n, T m) {
		return m ? Gcd(m, n % m) : n;
	}
	template <class T> T Lcm(T n, T m) {
		return n / Gcd(n, m) * m;
	}
	template <class T, class U = typename T::value_type> U Gcdv(const T& v) {
		return accumulate(next(v.begin()), v.end(), U(*v.begin()), Gcd<U>);
	}
	template <class T, class U = typename T::value_type> U Lcmv(const T& v) {
		return accumulate(next(v.begin()), v.end(), U(*v.begin()), Lcm<U>);
	}
	template <class T> T Pow(T a, T n) {
		T r = 1;
		while (n > 0) {
			if (n & 1) r *= a;
			a *= a;
			n /= 2;
		}
		return r;
	}
	template <class T> T Powmod(T a, T n, T m = MOD) {
		T r = 1;
		while (n > 0) {
			if (n & 1)
				r = r * a % m, n--;
			else
				a = a * a % m, n /= 2;
		}
		return r;
	}
}  // namespace

// --- dump --- //
#if __has_include(<library/dump.hpp>)
#include <library/dump.hpp>
#else
#define dump(...) ((void)0)
#endif

// ---------------------------------------------------------------- //
#line 2 "a.cpp"

int ask(int i, int j) {
	out('?', i + 1, j + 1).flush();
	return in.read<int>();
}

int main() {
	ini(n);
	VVI dist(n + 1);
	FOR(i, 1, n) dist[ask(0, i)].push_back(i);

	deque<int> ans;
	ans.push_back(0);
	ans.push_back(dist[1][0]);
	if (dist[1].size() == 2) {
		ans.push_front(dist[1][1]);
	}
	FOR(i, 2, n + 1) {
		if (dist[i].empty()) break;
		if (ask(dist[i][0], ans.back()) == 1) {
			ans.push_back(dist[i][0]);
			if (dist[i].size() == 2) {
				ans.push_front(dist[i][1]);
			}
		} else {
			ans.push_front(dist[i][0]);
			if (dist[i].size() == 2) {
				ans.push_back(dist[i][1]);
			}
		}
	}

	VI a(n);
	rep(i, n) a[i] = ans[i] + 1;
	out('!', a);
}
accuracy: 0.96875
time_ms: 110
memory_kb: 3672
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <math.h>
#include <map>
using namespace std;
typedef long long int ll;


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    int id=1;
    int mx=-1;
    for(int i=2;i<=n;i++){
        cout << "? " << 1 << " " << i << endl;
        int y; cin >> y;
        if(y>mx){
            mx=y;
            id=i;
        }
    }
    vector<int> res(n,0);
    res[0]=id;
    for(int i=1;i<=n;i++){
        if(i==id)continue;
        cout << "? " << i << " " << id << endl;
        int y; cin >> y;
        res[y]=i;
    }
    cout << "!";
    for(int i=0;i<n;i++){
        cout << " " << res[i];
    }
    cout << endl;
}
accuracy: 1
time_ms: 130
memory_kb: 3664
final_rank: 1

code_snippet: //#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>

using namespace std;

//----------------------- Print Function ----------------------//

inline void print() {
    cout << '\n';
}
template <typename First, typename... Rest>
void print(const First &first, const Rest &... rest) {
    cout << first << ' ';
    print(rest...);
}

template <typename T>
void print(const T &a) {
    for (auto e : a) cout << e << ' ';
    cout << '\n';
}

//------------------------- Libraries -------------------------//

//--------------------------- Solve ---------------------------//

void solve() {
    int N; cin >> N;    

    if (N == 1) {
        cout << "! 1\n";
        cout.flush();
        return;
    }

    vector<int> v(N+1); 
    for (int i = 2; i <= N; i++) {
        cout << "? " << "1 " << i << '\n';
        cout.flush();

        int a; cin >> a;
        v[i] = a; 
    }

    int max_i = max_element(v.begin(), v.end()) - v.begin();

    vector<int> ans(N);
    ans[0] = max_i;
    for (int i = 1; i <= N; i++) {
        if (i == max_i) continue;
        cout << "? " << i << ' ' << max_i << '\n';
        cout.flush();

        int a; cin >> a;
        ans[a] = i;
    }
    
    cout << '!' << ' ';
    for (int i = 0; i < N-1; i++) {
        cout << ans[i] << ' ';
    }
    cout << ans[N-1] << '\n';
    cout.flush();
}

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3876
final_rank: 7

code_snippet: //#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>

using namespace std;

//----------------------- Print Function ----------------------//

inline void print() {
    cout << '\n';
}
template <typename First, typename... Rest>
void print(const First &first, const Rest &... rest) {
    cout << first << ' ';
    print(rest...);
}

template <typename T>
void print(const T &a) {
    for (auto e : a) cout << e << ' ';
    cout << '\n';
}

//------------------------- Libraries -------------------------//

//--------------------------- Solve ---------------------------//

void solve() {
    int N; cin >> N;
    vector<int> v(N+1); 
    for (int i = 2; i <= N; i++) {
        cout << "? " << "1 " << i << '\n';
        cout.flush();

        int a; cin >> a;
        v[i] = a; 
    }

    int max_i = max_element(v.begin(), v.end()) - v.begin();

    vector<int> ans(N);
    ans[0] = max_i;
    for (int i = 1; i <= N; i++) {
        if (i == max_i) continue;
        cout << "? " << i << ' ' << max_i << '\n';
        cout.flush();

        int a; cin >> a;
        ans[a] = i;
    }
    
    cout << '!' << ' ';
    for (int i = 0; i < N-1; i++) {
        cout << ans[i] << ' ';
    }
    cout << ans[N-1] << '\n';
    cout.flush();
}

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 0.96875
time_ms: 100
memory_kb: 3884
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#include <stdio.h>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define rep1(i,n) for(ll i=1;i<=(ll)(n);i++)
#define rep3(i,n,m) for(ll i=(n);i<(ll)(m);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << (x) << endl
// #define max(a, b) ((a) > (b) ? (a) : (b))
// #define min(a, b) ((a) < (b) ? (a) : (b)) 
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
	return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
	o<<"{";
	for(const T& v:vc) o<<v<<",";
	o<<"}";
	return o;
}
using ll = long long;
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;
int _stoi(string s, int tmp=10){
	istringstream stm(s);
	int res;
	stm >> res;
	return res;
}
double _stod(string s, int tmp=10){
	istringstream stm(s);
	double res;
	stm >> res;
	return res;
}
template<typename T>string to_string(const T& n){
	std::ostringstream stm;
	stm << n;
	return stm.str();
}

int main(void){
    int N;
    cin >> N;
	if (N == 1) {
		cout << "! 1" << endl;
		return 0;
	}
	vector<int> vec(N+1), ans(N, 0);
    rep3(i,2,N+1) {
        cout << "? " << 1 << " " << i << endl;
        cout.flush();
		cin >> vec[i];
    }
	auto ma = max_element(all(vec));
	int ama = ma - vec.begin();
	ans[0] = ama;
	rep1(i, N){
		if(ama == i) continue;
		cout << "? " << ama << " " << i << endl;
		cout.flush();
		int d;
		cin >> d;
		ans[d] = i;
	}
	cout << "!";
	rep(i, N) cout << " " << ans[i];
}
accuracy: 1
time_ms: 110
memory_kb: 3884
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <math.h>
#include <map>
using namespace std;
typedef long long int ll;


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    int id=1;
    int mx=-1;
    for(int i=2;i<=n;i++){
        cout << "? " << 1 << " " << i << endl;
        int y; cin >> y;
        if(y>mx){
            mx=y;
            id=i;
        }
    }
    vector<int> res(n,0);
    res[0]=id;
    for(int i=1;i<=n;i++){
        if(i==id)continue;
        cout << "? " << i << " " << id << endl;
        int y; cin >> y;
        res[y]=i;
    }
    cout << "!";
    for(int i=0;i<n;i++){
        cout << " " << res[i];
    }
    cout << endl;
}
accuracy: 1
time_ms: 130
memory_kb: 3692
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#include <stdio.h>
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define rep1(i,n) for(ll i=1;i<=(ll)(n);i++)
#define rep3(i,n,m) for(ll i=(n);i<(ll)(m);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << (x) << endl
// #define max(a, b) ((a) > (b) ? (a) : (b))
// #define min(a, b) ((a) < (b) ? (a) : (b)) 
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
	return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
	o<<"{";
	for(const T& v:vc) o<<v<<",";
	o<<"}";
	return o;
}
using ll = long long;
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;
int _stoi(string s, int tmp=10){
	istringstream stm(s);
	int res;
	stm >> res;
	return res;
}
double _stod(string s, int tmp=10){
	istringstream stm(s);
	double res;
	stm >> res;
	return res;
}
template<typename T>string to_string(const T& n){
	std::ostringstream stm;
	stm << n;
	return stm.str();
}

int main(void){
    int N;
    cin >> N;
	vector<int> vec(N+1), ans(N, 0);
    rep3(i,2,N+1) {
        cout << "? " << 1 << " " << i << endl;
        cout.flush();
		cin >> vec[i];
    }
	auto ma = max_element(all(vec));
	int ama = ma - vec.begin();
	ans[0] = ama;
	rep1(i, N){
		if(ama == i) continue;
		cout << "? " << ama << " " << i << endl;
		cout.flush();
		int d;
		cin >> d;
		ans[d] = i;
	}
	cout << "!";
	rep(i, N) cout << " " << ans[i];
}
accuracy: 0.96875
time_ms: 110
memory_kb: 3880
final_rank: 19

code_snippet: #define  _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma comment (linker, "/STACK:526000000")
#include "bits/stdc++.h"
using namespace std;
typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a,b) for(long long (a) = 0;(a) < (b);++(a))
#define ALL(x) (x).begin(),(x).end()
unsigned long xor128() {
	static unsigned long x = 123456789, y = 362436069, z = 521288629, w = 88675123;
	unsigned long t = (x ^ (x << 11));
	x = y; y = z; z = w;
	return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
};
void init() {
	iostream::sync_with_stdio(false);
	cout << fixed << setprecision(100);
}
int cnter[30000];
vector<int> kazu[30000];
void solve(){
	int n;
	cin >> n;
	REP(i, n-1) {
		cout << "? 1 " << i + 2 << endl;
		int a;
		cin >> a;
		cnter[a]++;
		kazu[a].push_back(i + 2);
	}
	int target = 1;
	if (kazu[1].size() != 1) {
		for (int i = 1; i < 1e9; ++i) {
			if (kazu[i].size() == 1) {
				//i-1 is target
				cout << "? " << kazu[i][0] << " " << kazu[i-1][0] << endl;
				int gogo;
				cin >> gogo;
				if (gogo == 1) {
					target = kazu[i - 1][1];
				}
				else {
					target = kazu[i - 1][0];
				}
			}
			else if (kazu[i].size() == 0) {
				target = kazu[i - 1][0];
			}
		}
	}
	vector<pair<int, int>> ans;
	REP(i, n) {
		cout << "? " << i + 1 << " " << target << endl;
		int a;
		cin >> a;
		ans.push_back(mp(a, i+1));
	}
	sort(ALL(ans));
	cout << "!";
	REP(i, ans.size()) {
		cout << " " << ans[i].second;
	}
	cout << endl;
}

int main() {
	init();
	solve();
}
accuracy: 0.03125
time_ms: 10
memory_kb: 3892
final_rank: 20

code_snippet: #pragma GCC target("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
// #include<ext/pb_ds/assoc_container.hpp>
// #include<ext/pb_ds/tree_policy.hpp>
// #include<ext/pb_ds/tag_and_trait.hpp>
// using namespace __gnu_pbds;
// #include<boost/multiprecision/cpp_int.hpp>
// namespace multiprecisioninteger = boost::multiprecision;
// using cint=multiprecisioninteger::cpp_int;
using namespace std;
using ll=long long;
#define double long double
using datas=pair<ll,ll>;
using ddatas=pair<double,double>;
using tdata=pair<ll,datas>;
using vec=vector<ll>;
using mat=vector<vec>;
using pvec=vector<datas>;
using pmat=vector<pvec>;
// using llset=tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;
#define For(i,a,b) for(i=a;i<(ll)b;++i)
#define bFor(i,b,a) for(i=b,--i;i>=(ll)a;--i)
#define rep(i,N) For(i,0,N)
#define rep1(i,N) For(i,1,N)
#define brep(i,N) bFor(i,N,0)
#define brep1(i,N) bFor(i,N,1)
#define all(v) (v).begin(),(v).end()
#define allr(v) (v).rbegin(),(v).rend()
#define vsort(v) sort(all(v))
#define vrsort(v) sort(allr(v))
#define endl "\n"
#define eb emplace_back
#define print(x) cout<<x<<endl
#define printyes print("Yes")
#define printno print("No")
#define printYES print("YES")
#define printNO print("NO")
#define output(v) do{bool f=0;for(auto outi:v){cout<<(f?" ":"")<<outi;f=1;}cout<<endl;}while(0)
#define matoutput(v) do{for(auto outimat:v)output(outimat);}while(0)
const ll mod=1000000007;
// const ll mod=998244353;
const ll inf=1LL<<60;
const double PI=acos(-1);
const double eps=1e-9;
template<class T,class E> ostream& operator<<(ostream& os,pair<T,E>& p){return os<<"{"<<p.first<<","<<p.second<<"}";}
template<class T> inline bool chmax(T& a,T b){bool x=a<b;if(x)a=b;return x;}
template<class T> inline bool chmin(T& a,T b){bool x=a>b;if(x)a=b;return x;}

void startupcpp(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout<<fixed<<setprecision(15);
}

double distance(ddatas x,ddatas y){
  double a=x.first-y.first,b=x.second-y.second;
  return sqrt(a*a+b*b);
}

ll modinv(ll a,ll m=mod) {
  ll b=m,u=1,v=0,t;
  while(b){
    t=a/b;
    a-=t*b; swap(a,b);
    u-=t*v; swap(u,v);
  }
  return (u+m)%m;
}

ll moddevide(ll a,ll b){return (a*modinv(b))%mod;}

vec modncrlistp,modncrlistm;

ll modncr(ll n,ll r){
  if(n<r)return 0;
  ll i,size=modncrlistp.size();
  if(size<=n){
    modncrlistp.resize(n+1);
    modncrlistm.resize(n+1);
    if(!size){
      modncrlistp[0]=modncrlistm[0]=1;
      size++;
    }
    For(i,size,n+1){
      modncrlistp[i]=modncrlistp[i-1]*i%mod;
      modncrlistm[i]=modinv(modncrlistp[i]);
    }
  }
  return modncrlistp[n]*modncrlistm[r]%mod*modncrlistm[n-r]%mod;
}

ll modpow(ll a,ll n,ll m=mod){
  ll res=1;
  while(n>0){
    if(n&1)res=res*a%m;
    a=a*a%m;
    n>>=1;
  }
  return res;
}

ll gcd(ll a,ll b){if(!b)return abs(a);return (a%b==0)?abs(b):gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}

ll countdigits(ll n){
  ll ans=0;
  while(n){n/=10;ans++;}
  return ans;
}

ll sumdigits(ll n){
  ll ans=0;
  while(n){ans+=n%10;n/=10;}
  return ans;
}
ll N,M,K,H,W,A,B,C,D;
string s,t;
ll ans;
int main(){
  // startupcpp();
  // int codeforces;cin>>codeforces;while(codeforces--){
  ll i,j;
  cin>>N;
  vec v(N);
  v[0]=0;
  For(i,2,N+1){
    cout<<"? 1 "<<i<<endl;
    cin>>v[i-1];
  }
  auto itr=max_element(all(v))-v.begin();
  rep(i,N){
    if(i!=itr){
      cout<<"? "<<itr+1<<" "<<i+1<<endl;
      cin>>v[i];
    }else{
      v[i]=0;
    }
  }
  pvec ans(N);
  rep(i,N)ans[i]=datas(v[i],i+1);
  vsort(ans);
  cout<<"!";
  rep(i,N)cout<<" "<<ans[i].second;
  cout<<endl;
  // }
}
accuracy: 1
time_ms: 110
memory_kb: 3884
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll MOD=1000000007;
const ll MOD2=998244353;
const double PI=acos(-1);
const ll INF=1e18;
typedef pair<ll,ll> P;
typedef vector<ll> vl;
typedef vector<vl> vvl;
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define rep(i,n) FOR(i,0,n)
string abc="abcdefghijklmnopqrstuvwxyz";
string ABC="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
struct edge{ll to,cost;};

ll q(ll a,ll b){
    cout << "? " << a << " " << b << endl;
    cout.flush();
    ll d;
    cin >> d;
    return d;
}

int main() {
    ll n;
    cin >> n;
    ll x,c,mx=0;
    if(n==1){
        cout << "! 1"<< endl;
    }
    else{
    rep(i,n-1){
        x=q(1,i+2);
        if(mx<x){
            mx=x;
            c=i+2;
        }
    }
    vl ans(n);
    ans[0]=c;
    rep(i,n){
        if(i+1==c){
            continue;
        }
        else{
            x=q(i+1,c);
            ans[x]=i+1;
        }
    }
    cout << "!";
    rep(i,n){
        cout << " " << ans[i];
    }
    cout << endl;
    }
}
accuracy: 1
time_ms: 280
memory_kb: 3648
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll MOD=1000000007;
const ll MOD2=998244353;
const double PI=acos(-1);
const ll INF=1e18;
typedef pair<ll,ll> P;
typedef vector<ll> vl;
typedef vector<vl> vvl;
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define rep(i,n) FOR(i,0,n)
string abc="abcdefghijklmnopqrstuvwxyz";
string ABC="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
struct edge{ll to,cost;};

ll q(ll a,ll b){
    cout << "? " << a << " " << b << endl;
    cout.flush();
    ll d;
    cin >> d;
    return d;
}

int main() {
    ll n;
    cin >> n;
    ll x,c,mx=0;
    rep(i,n-1){
        x=q(1,i+2);
        if(mx<x){
            mx=x;
            c=i+2;
        }
    }
    vl ans(n);
    ans[0]=c;
    rep(i,n){
        if(i+1==c){
            continue;
        }
        else{
            x=q(i+1,c);
            ans[x]=i+1;
        }
    }
    cout << "!";
    rep(i,n){
        cout << " " << ans[i];
    }
    cout << endl;
}
accuracy: 0.96875
time_ms: 280
memory_kb: 3644
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T, class U> bool chmax(T& a, const U& b){ if(a < b){ a = b; return 1; } return 0; }

int query(int a, int b){
    cout << "? " << a + 1 << ' ' << b + 1 << endl;
    int ans;
    cin >> ans;
    return ans;
}
void answer(const vector<int>& a){
    cout << '!';
    for(int i : a) cout << ' ' << i + 1;
    cout << endl;
}
int main() {
    int n;
    cin >> n;
    int max = 0, idx;
    for(int i = 0; i < n; i++) if(chmax(max, query(0, i))) idx = i;
    vector<int> ans(n);
    for(int i = 0; i < n; i++) ans[query(idx, i)] = i;
    answer(ans);
}
accuracy: 1
time_ms: 280
memory_kb: 3668
final_rank: 9

code_snippet: #include <iostream>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <map>
#include <math.h>
#include <string.h>
#include <iomanip>
#include <numeric>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <functional>
#include <limits>
#include <cassert>
#include <bitset>

using namespace std;

/* template */

using ll = long long;

void debug_out() { std::cout << std::endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cout << H << " ";
  debug_out(T...);
}

#ifdef LOCAL
#define debug(...) cout << "debug: "; debug_out(__VA_ARGS__)
#else
#define debug(...) 
#endif

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n-1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (long long i = (long long)(a); i< (long long)(n); i++)
#define RRep(i, a, n) for (long long i = ((long long)(n-1ll)); i>=(long long)(a); i--)
#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()

/* xxpoxx's definition */
#define FOR(i, a, b) for (ll i = (a); i < (b); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) (a).begin(), (a).end()
using vl = vector<ll>;
string abc = "abcdefghijklmnopqrstuvwxyz";
string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
  for (std::size_t i = 0; i < vec.size(); i++)os << vec[i] << (i + 1 == vec.size() ? "" : " ");
  return os;
}

struct Edge{
    int to;
    ll weight;
    Edge(int t, ll w) : to(t), weight(w){ }
};

struct edge{
    int from;
    int to;
    ll weight;
    edge(int f,int t,ll w) : from(f), to(t), weight(w){ }
};


using Graph = vector<vector<Edge>>;
using graph = vector<vector<int>>;
using edges = vector<edge>;

template <class T>
inline bool chmin(T &a, T b){
    if (a > b){
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b){
    if (a < b){
        a = b;
        return true;
    }
    return false;
}

template <class T>
T lcm(T a, T b){
    return (a*b)/gcd(a,b);
}

constexpr ll LNF = 1LL<<60;

constexpr int INF = 1e9+7;

const double PI=3.14159265358979323846;


vector<int> dx = {-1,0,1,0,-1,1,-1,1};
vector<int> dy = {0,-1,0,1,1,-1,-1,1};

/* template */

int main(){
    // c書いてますね
    ll n;
    cin >> n;
    map<ll, ll> one_to;
    ll ma = 0;
    ll haji;
    for(ll i = 2; i < n+1; i++){
        cout << "? 1 ";
        cout << i << endl;
        ll tmp;
        cin >> tmp;
        one_to[i] = tmp;
        if(tmp > ma){
            ma = tmp;
            haji = i;
        }
    }
    vector<pair<ll,ll>> hajikara;
    for(ll i = 1; i < n+1; i++){
        if(i == 1){
            hajikara.push_back(make_pair(ma, 1));
            continue;
        }
        if(i == haji){
            hajikara.push_back(make_pair(0, haji));
            continue;
        }
        cout << "? " << haji << " " << i << endl;
        ll tmp;
        cin >> tmp;
        hajikara.push_back(make_pair(tmp, i));
    }
    sort(ALL(hajikara));
    vector<ll> ans;
    REP(i, n){
        ans.push_back(hajikara[i].second);
    }
    cout <<"! ";
    REP(i, n){
        if(i == n-1){
            cout << ans[i];
        }else{
            cout << ans[i] << " ";
        }
    }
    cout << endl;
    /*
    ll N,S,P,C;
    cin >>N;
    vector<ll> r(N),score(N),Sr(N),Pr(N),Cr(N);
    for(ll i=0;i<N;i++) cin >>r[i];
    vector<pair<ll,ll>> s(N), p(N), c(N);
    for(ll i=0;i<N;i++){
        ll a1,a2,a3;
        cin >>a1>>a2>>a3;
        s[i]=make_pair(a1,i);
        p[i]=make_pair(a2,i);
        c[i]=make_pair(a3,i);
    }
    S=s[0].first; P=p[0].first; C=c[0].first;
    sort(s.begin(),s.end());
    sort(p.begin(),p.end());
    sort(c.begin(),c.end());
    reverse(s.begin(),s.end());
    reverse(p.begin(),p.end());
    reverse(c.begin(),c.end());
    //スマイルの初期点計算
    ll douritsu=0;
    ll rank=0;
    for(ll i=0;i<N;i++){
        score[s[i].second]+=r[rank];
        Sr[s[i].second]=rank;
        if(i!=N-1){
            if(s[i].first==s[i+1].first) douritsu++;
            else{
                rank+=douritsu+1;
                douritsu=0;
            }
        }
    }
    //ぴゅあの初期点計算
    douritsu=0;
    rank=0;
    for(ll i=0;i<N;i++){
        score[p[i].second]+=r[rank];
        Pr[p[i].second]=rank;
        if(i!=N-1){
            if(p[i].first==p[i+1].first) {
                douritsu++;
            }else{
                rank+=douritsu+1;
                douritsu=0;
            }
        }
    }
    //くーるの初期点計算
    douritsu=0;
    rank=0;
    for(ll i=0;i<N;i++){
        score[c[i].second]+=r[rank];
        Cr[c[i].second]=rank;
        if(i!=N-1){
            if(c[i].first==c[i+1].first) {
                douritsu++;
            }else{
                rank+=douritsu+1;
                douritsu=0;
            }
        }
    }
    vector<ll> score2 = score;
    ll ans=LNF;
    //for(ll j=1; j<N; j++) cout << score[j] << endl;
    // すまいるを値変えるとき
    for(ll i=S+1;i<=100;i++){
        for(ll j=0;j<N;j++){
            if(s[j].second==0) continue;
            if(s[j].first>i) continue;
            else if(s[j].first==i) score2[0]+=r[j]-r[Sr[0]];
            else if(s[j].first>=s[0].first) score2[j]+=r[Sr[j]]-r[Sr[j]+1];
        }
        ll rank=N;
        for(ll j=1; j<N; j++) {
            if(score2[j]<=score2[0]) rank--;
        }
        cout << i << " " << rank << endl;
        if(rank<=8) ans=min(ans,i-S);
    }
    cout << ans;
    */
}
accuracy: 1
time_ms: 290
memory_kb: 3960
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
using ld = long double;

#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define ALL(x) ((x).begin()), ((x).end())

#define XOR(x, y) (((x) && (y)) || ((!(x)) && (!(y))))

#define READ(x) (cin >> (x))
#define WRITE_N(x) (cout << (x) << endl)
#define WRITE(x) (cout << (x))
#define WRITE_YESNO(x) (WRITE_N((x) ? "Yes" : "No"))

#define PRESICE_COUT std::cout << std::setprecision(15) << std::fixed

int ask_distance(int a, int b) {
  cout << "? " << a << " " << b << endl;
  int x;
  cin >> x;
  return x;
}

void guess(deque<int> &que) {
  cout << "! ";
  for (auto x : que) {
    cout << x << (x != que.back() ? " " : "");
  }
  cout << endl;
}

int main() {
  // get values from input
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N;
  cin >> N;

  // main procedure

  // dist: 0 base, order: 1 base
  vector<vector<int>> imagawa_on_distance(N - 1, vector<int>());
  for (size_t i = 2; i <= N; i++) {
    int d = ask_distance(1, i);
    imagawa_on_distance[d - 1].push_back(i);
  }

  // order: 1 base
  deque<int> imagawa_row;
  imagawa_row.push_back(1);

  // for (auto v : imagawa_on_distance) {
  //     for (auto x : v) {
  //       cout << x << " ";
  //     }
  //     cout << endl;
  // }

  for (size_t i = 0; i < N - 1; i++) {
    if (imagawa_on_distance[i].size() == 0) {
      break;
    } else if (imagawa_on_distance[i].size() == 1) {
      int distance_from_back =
          ask_distance(imagawa_on_distance[i][0], imagawa_row.back());

      if (distance_from_back == 1) {
        imagawa_row.push_back(imagawa_on_distance[i][0]);
      } else {
        imagawa_row.push_front(imagawa_on_distance[i][0]);
      }
    } else {
      // ###DEBUG###
      //   cout << "distance(0 base) = " << i << endl;
      //   for (auto x : imagawa_row) {
      //     cout << x << (x == imagawa_row.back() ? " " : "");
      //   }
      //   cout << endl;
      // ##########

      int distance_from_back =
          ask_distance(imagawa_on_distance[i][0], imagawa_row.back());

      if (distance_from_back == 1) {
        imagawa_row.push_back(imagawa_on_distance[i][0]);
        imagawa_row.push_front(imagawa_on_distance[i][1]);
      } else {
        imagawa_row.push_front(imagawa_on_distance[i][0]);
        imagawa_row.push_back(imagawa_on_distance[i][1]);
      }
    }
  }

  // output
  guess(imagawa_row);

  return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 3648
final_rank: 4

code_snippet: #include "bits/stdc++.h"
using namespace std;
using lint=int64_t;

lint q(lint a,lint b){
	cout<<"? "<<a<<" "<<b<<endl;
	cout.flush();
	lint r; cin>>r;
	return r;
}

int main(){
	lint n,c=0,mx=0; cin>>n;
	for(int i=1; i<n; ++i){
		lint r=q(1,i+1);
		if(mx<r){
			mx=r;
			c=i;
		}
	}
	vector<lint>ans(n);
	ans[0]=c+1;
	for(int i=0; i<n; ++i){
		if(c==i)continue;
		lint r=q(c+1,i+1);
		ans[r]=i+1;
	}
	cout<<"!";
	for(auto e:ans)cout<<" "<<e;
	cout<<endl;
	return 0;
}
accuracy: 1
time_ms: 280
memory_kb: 3668
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(x) (x).begin(),(x).end()
#define ll long long
#define ld long double
#define vl vector<long long>
#define vvl vector<vector<long long>>
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rep2(i, s, n) for (ll i = (s); i < (ll)(n); i++)
#define rrep(i, x) for (ll i = ((ll)(x)-1); i >= 0; i--)
#define pll pair<long long,long long>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define vvc vector<vector<char>>
#define vc vector<char>
#define vvb vector<vector<bool>>
#define vb vector<bool>
#define elif else if
#define maxe(x) *max_element(all(x))
#define mine(x) *min_element(all(x))
#define Size(x) ((int)(x).size())
const long long INF = 1LL << 60;
const long double pi = 3.1415926535897932;
long long MOD = 1000000007;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};

    template<class T> inline bool chmin(T& a, T b) {
        if (a > b) {
            a = b;
            return true;
        }
        return false;
    }
    template<class T> inline bool chmax(T& a, T b) {
        if (a < b) {
            a = b;
            return true;
        }
        return false;
    }

    vector<long long> divisor(long long n) {
        vector<long long> ret;
        for (long long i = 1; i * i <= n; i++) {
            if (n % i == 0) {
                ret.push_back(i);
                if (i * i != n) ret.push_back(n / i);
            }
        }
        sort(ret.begin(), ret.end()); // 昇順に並べる
        return ret;
    }

    map< ll, ll > prime_factor(ll n) {
        map< ll, ll > ret;
        for(ll i = 2; i * i <= n; i++) {
            while(n % i == 0) {
                ret[i]++;
                n /= i;
            }
        }
        if(n != 1) ret[n] = 1;
        return ret;
    }

    //(mod m)でのaの逆元を計算する
    //a/b(mod m)=a(mod m)*modinv(b,m)
    long long modinv(long long a, long long m) {
        long long b = m, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        u %= m;
        if (u < 0) u += m;
        return u;
    }

    long long modpow(long long a, long long n, long long mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    ll modnCr(ll n, ll r, ll mod) {
        ll res = 1;
        rep (i, r) {
          res = res * (n - i) % mod * modpow(i + 1, mod - 2, mod) % mod;
        }
        return res;
      }

    struct UnionFind {
        vector<int> par;
    
        UnionFind(int n) : par(n, -1) { }
    
        int root(int x) {
            if (par[x] < 0) return x;
            else return par[x] = root(par[x]);
        }
    
        bool issame(int x, int y) {
            return root(x) == root(y);
        }
    
        bool merge(int x, int y) {
            x = root(x); y = root(y);
            if (x == y) return false;
            if (par[x] > par[y]) swap(x, y); // merge technique
            par[x] += par[y];
            par[y] = x;
            return true;
        }
    
        int size(int x) {
            return -par[root(x)];
        }
    };
//mint,----------------------------------------------------
    signed main(){
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        ll N;
        cin>>N;
        pll p;
        p=mp(-1*INF,1);// 1距離2num
        rep(i,N-1){
            cout<<'?'<<' '<<1<<' '<<i+2<<endl;
            cout.flush();
            ll D;
            cin>>D;
            if(D>=p.first){
                p.first=D;
                p.second=i+2;
            }
        }
        vl Ans(N);
        Ans[0]=p.second;
        rep(i,N){
            if(i==p.second-1)continue;
            cout<<"? "<<p.second<<" "<<i+1<<endl;
            cout.flush();
            ll D;
            cin>>D;
            Ans[D]=i+1;
        }
        cout<<"! ";
        rep(i,N){
            cout<<Ans[i];
            if(i==N-1)continue;
            cout<<' ';
        }
        cout<<endl;
    }
accuracy: 1
time_ms: 280
memory_kb: 3648
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(x) (x).begin(),(x).end()
#define ll long long
#define ld long double
#define vl vector<long long>
#define vvl vector<vector<long long>>
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rep2(i, s, n) for (ll i = (s); i < (ll)(n); i++)
#define rrep(i, x) for (ll i = ((ll)(x)-1); i >= 0; i--)
#define pll pair<long long,long long>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define vvc vector<vector<char>>
#define vc vector<char>
#define vvb vector<vector<bool>>
#define vb vector<bool>
#define elif else if
#define maxe(x) *max_element(all(x))
#define mine(x) *min_element(all(x))
#define Size(x) ((int)(x).size())
const long long INF = 1LL << 60;
const long double pi = 3.1415926535897932;
long long MOD = 1000000007;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};

    template<class T> inline bool chmin(T& a, T b) {
        if (a > b) {
            a = b;
            return true;
        }
        return false;
    }
    template<class T> inline bool chmax(T& a, T b) {
        if (a < b) {
            a = b;
            return true;
        }
        return false;
    }

    vector<long long> divisor(long long n) {
        vector<long long> ret;
        for (long long i = 1; i * i <= n; i++) {
            if (n % i == 0) {
                ret.push_back(i);
                if (i * i != n) ret.push_back(n / i);
            }
        }
        sort(ret.begin(), ret.end()); // 昇順に並べる
        return ret;
    }

    map< ll, ll > prime_factor(ll n) {
        map< ll, ll > ret;
        for(ll i = 2; i * i <= n; i++) {
            while(n % i == 0) {
                ret[i]++;
                n /= i;
            }
        }
        if(n != 1) ret[n] = 1;
        return ret;
    }

    //(mod m)でのaの逆元を計算する
    //a/b(mod m)=a(mod m)*modinv(b,m)
    long long modinv(long long a, long long m) {
        long long b = m, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        u %= m;
        if (u < 0) u += m;
        return u;
    }

    long long modpow(long long a, long long n, long long mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    ll modnCr(ll n, ll r, ll mod) {
        ll res = 1;
        rep (i, r) {
          res = res * (n - i) % mod * modpow(i + 1, mod - 2, mod) % mod;
        }
        return res;
      }

    struct UnionFind {
        vector<int> par;
    
        UnionFind(int n) : par(n, -1) { }
    
        int root(int x) {
            if (par[x] < 0) return x;
            else return par[x] = root(par[x]);
        }
    
        bool issame(int x, int y) {
            return root(x) == root(y);
        }
    
        bool merge(int x, int y) {
            x = root(x); y = root(y);
            if (x == y) return false;
            if (par[x] > par[y]) swap(x, y); // merge technique
            par[x] += par[y];
            par[y] = x;
            return true;
        }
    
        int size(int x) {
            return -par[root(x)];
        }
    };
//mint,----------------------------------------------------
    signed main(){
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        ll N;
        cin>>N;
        pll p;
        p=mp(-1*INF,INF);// 1距離2num
        rep(i,N-1){
            cout<<'?'<<' '<<1<<' '<<i+2<<endl;
            cout.flush();
            ll D;
            cin>>D;
            if(D>=p.first){
                p.first=D;
                p.second=i+2;
            }
        }
        vl Ans(N);
        Ans[0]=p.second;
        rep(i,N){
            if(i==p.second-1)continue;
            cout<<"? "<<p.second<<" "<<i+1<<endl;
            cout.flush();
            ll D;
            cin>>D;
            Ans[D]=i+1;
        }
        cout<<"! ";
        rep(i,N){
            cout<<Ans[i];
            if(i==N-1)continue;
            cout<<' ';
        }
        cout<<endl;
    }
accuracy: 0.96875
time_ms: 270
memory_kb: 3624
final_rank: 16

code_snippet: #include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <string>
#include <vector>

using usize = std::size_t;
using u32 = std::uint32_t;

template <class T> void chmin(T& a, const T& b) {
  if (b < a)
    a = b;
}

usize ask(const usize x, const usize y) {
  if (x == y) {
    return 0;
  }
  std::cout << "? " << x + 1 << " " << y + 1 << std::endl;
  usize r;
  std::cin >> r;
  return r;
}

void exc(const std::vector<usize>& a) {
  std::cout << "!";
  for (const auto e : a) {
    std::cout << " " << e + 1;
  }
  std::cout << std::endl;
}

int main() {

  usize n;
  std::cin >> n;

  usize far, dist = 0;
  for (usize i = 0; i != n; ++i) {
    usize d = ask(0, i);
    if (d >= dist) {
      dist = d;
      far = i;
    }
  }

  std::vector<usize> ans(n);
  for (usize i = 0; i != n; ++i) {
    ans[ask(far, i)] = i;
  }

  exc(ans);

  return 0;
}
accuracy: 1
time_ms: 280
memory_kb: 3668
final_rank: 9