Problem:
D - Parallel Sort
問題文
これはインタラクティブな問題です。
$1$ 以上 $2^N$ 以下の整数を並び替えた順列 $P$ が隠されています。
あなたは以下の操作を $60$ 回だけ行うことができます。
操作によって $P$ を特定してください。
操作
長さ $2^N$ の整数列 $A$ を宣言する。
$A$ の要素は $1$ 以上 $2^N$ 以下の整数でなければならない。
長さ $2^N$ の整数列 $C$ が用意される。
$C$ の要素ははじめすべて $0$ である。
各 $i$ $(1 \le i \le 2^N)$ について、次が行われる。
$P_{A_i} > P_i$ のとき、$C_{A_i}$ に $1$ を足す。
そうでなければ何もしない。
その後、$C$ の内容があなたに伝えられる。
制約
$1 \leq N \leq 10$
$N$ は整数である。
$P$ は $1$ 以上 $2^N$ 以下の整数を並び替えた順列である。
入出力
最初に、$N$ が標準入力から与えられる。
$N$
その後、何回か操作を繰り返す。操作では次の形式で標準出力へ出力せよ。
? $A_1$ $A_2$ $\ldots$ $A_{2^N}$
ここで、$A_i$ $(1 \le i \le 2^N)$ は $1$ 以上 $2^N$ 以下の整数でなければならない。
この操作に対する応答は、次の形式で標準入力から与えられる。
$C_1$ $C_2$ $\ldots$ $C_{2^N}$
最後に、特定した順列 $P$ を以下の形式で標準出力へ出力せよ。
! $P_1$ $P_2$ $\ldots$ $P_{2^N}$
注意
出力の度に標準出力を
flush
せよ。そうしない場合、
TLE
となる可能性がある。
順列 $P$ を出力した後は、プログラムをすぐに終了せよ。従わない場合のジャッジの挙動は未定義である。
出力形式が正しくない場合のジャッジの挙動は未定義である。
入出力例
$N = 2, P = (4, 1, 3, 2)$ としたときの入出力例を以下に示す。
入力
出力
備考
2
最初に $N$ が入力される。
? 4 4 1 1
2 0 0 1
$P_4 > P_2$ だから、$C_4$ に $1$ が足される。
$P_1 > P_3$ だから、$C_1$ に $1$ が足される。
$P_1 > P_4$ だから、$C_1$ に $1$ が足される。
? 1 3 3 3
0 0 2 0
$P_3 > P_2$ だから、$C_3$ に $1$ が足される。
$P_3 > P_4$ だから、$C_3$ に $1$ が足される。
! 4 1 3 2
最後に順列 $P$ を出力する。

Submitted solutions:

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acos(-1.0);


vector<int> query(vector<int> a) {
	cout << "?";
	rep(i, a.size()) {
	    cout << " ";
		cout << a[i]+1;
	}
	cout << endl;
	vector<int> res(a.size());
	rep(i, a.size())cin >> res[i];
	return res;
}
void solve() {
	int n; cin >> n;
	vector<vector<int>> v;
	rep(i, (1<<n)) {
		v.push_back({ i });
	}
	int tmp = 0;
	while (v.size() > 1) {
		tmp++;
		vector<vector<int>> ups;
		vector<vector<vector<int>>> vs;
		vector<vector<vector<int>>> ts;
		vector<vector<int>> locs;
		locs.resize(v.size() / 2);
		rep(j, locs.size()) {
			locs[j].resize(v[0].size());
		}
		rep(i, v.size() / 2) {
			ups.push_back({ -1 });
			vs.push_back({ v[2 * i] });
			ts.push_back({ v[2 * i + 1] });
		}
		vector<bool> ist(1 << n);
		for (int i = 1; i < v.size(); i += 2) {
			for (int id : v[i]) {
				ist[id] = true;
			}
		}
		rep(aa, tmp) {
			vector<int> q(1 << n);
			rep(i, (1 << n))if (ist[i])q[i] = i;
			rep(i, v.size() / 2) {
				rep(j, vs[i].size()) {
					if (ts[i][j].empty()) {
						for (int id : vs[i][j]) {
							q[id] = ups[i][j];
						}
					}
					else {
						int mid = ts[i][j].size() / 2;
						for (int id : vs[i][j]) {
							q[id] = ts[i][j][mid];
						}
					}
				}
			}
			vector<int> c = query(q);
			vector<vector<int>> nup(v.size() / 2);
			rep(i, v.size() / 2) {
				int s = 0;
				int t = 0;

				vector<vector<int>> nv;
				vector<vector<int>> nt;
				rep(j, vs[i].size()) {
					if (ts[i][j].empty()) {
						nv.push_back(vs[i][j]);
						nt.push_back(ts[i][j]);
						nup[i].push_back(ups[i][j]);
					}
					else {
						int mid = ts[i][j].size() / 2;
						int num = ts[i][j][mid];
						locs[i][t + mid] = s + c[num];
						vector<int> vl;
						vector<int> vr;
						rep(k, vs[i][j].size()) {
							if (k < c[num]) {
								vl.push_back(vs[i][j][k]);
							}
							else vr.push_back(vs[i][j][k]);
						}
						vector<int> tl, tr;
						rep(k, ts[i][j].size()) {
							if (k < mid)tl.push_back(ts[i][j][k]);
							else if (k > mid)tr.push_back(ts[i][j][k]);
						}
						nv.push_back(vl); nv.push_back(vr);
						nt.push_back(tl); nt.push_back(tr);
						nup[i].push_back(num);
						nup[i].push_back(num);
					}

					s += vs[i][j].size();
					t += ts[i][j].size();
					if (ups[i][j] >= 0)t++;
				}
				swap(vs[i], nv);
				swap(ts[i], nt);
			}
			swap(ups, nup);
		}
		vector<vector<int>> nv;
		rep(i, v.size() / 2) {
			int id = 0;
			vector<int> cv;
			rep(j, v[2 * i].size()) {
				while (id < v[2 * i + 1].size() && locs[i][id] <= j) {
					cv.push_back(v[2 * i + 1][id]);
					id++;
				}
				cv.push_back(v[2 * i][j]);
			}
			while (id < v[2 * i + 1].size()) {
				cv.push_back(v[2 * i + 1][id]);
				id++;
			}
			nv.push_back(cv);
		}
		swap(v, nv);
		/*rep(i, v.size()) {
			rep(j, v[i].size()) {
				cout << v[i][j] << " ";
			}
			cout << "\n";
		}*/
	}
	//cout << "?? " << v[0].size() << "\n";
	vector<int> ans(1<<n);
	rep(i, (1 << n)) {
		ans[v[0][i]] = i;
	}
	cout << "!";
	rep(i, (1 << n)) {
		cout << " " << ans[i] + 1;
	}
	cout << endl;
}





signed main() {
	//ios::sync_with_stdio(false);
	//cin.tie(0);
	solve();
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3436
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

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

const long long INF = 1e18;
//const ll mod = 1000000007;

const ll LOCAL = 0;
ll N;
ll C[3000];
ll A[3000];
vector<ll> ANS;
vector<vector<ll>> v;
vector<ll> ans;
int Timer = 0;

void printans() {
    assert(v.size() == 1);
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            if(v[0][j] == i) ans.push_back(j);
        }
    }
    cout << "!";
    for(auto tmp : ans) {
        cout << " " << tmp + 1;
    }
    cout << endl;
    if(LOCAL) {
        for(int i = 0; i < N; i++) {
            cerr << ANS[v[0][i]] << " ";
        }
        cerr << endl;
        for(int i = 0; i < N; i++) {
            assert(ANS[v[0][i]] == i);
            assert(ans[i] == ANS[i]);
        }
    }
}

void ask() {
    if(LOCAL) {
        Timer++;
        assert(Timer <= 60);
        for(int i = 0; i < N; i++) C[i] = 0;
        for(int i = 0; i < N; i++) {
            if(ANS[A[i]] > ANS[i]) C[A[i]]++;
        }
    } else {
        cout << "?";
        for(int i = 0; i < N; i++) {
            cout << " " << A[i] + 1;
        }
        cout << endl;
        for(int i = 0; i < N; i++) {
            cin >> C[i];
        }
    }
}

typedef pair<vector<ll>, vector<ll>> V_V;
int needed = 0;

vector<ll> g(V_V V, vector<ll> ok) {
    vector<ll> ret;
    l_l idx = {0, 0};
    while(idx.first != V.first.size() or idx.second != V.second.size()) {
        if(idx.first == V.first.size()) {
            ret.push_back(V.second[idx.second]);
            idx.second++;
            continue;
        }
        if(idx.second == V.second.size()) {
            ret.push_back(V.first[idx.first]);
            idx.first++;
            continue;
        }
        if(ok[idx.first] <= idx.second) {
            ret.push_back(V.first[idx.first]);
            idx.first++;
            continue;
        }
        if(ok[idx.first] > idx.second) {
            ret.push_back(V.second[idx.second]);
            idx.second++;
            continue;
        }
        assert(0);
    }
    return ret;
}

vector<vector<ll>> f(vector<V_V> V) {
    /*
    for(auto tmp : V) {
        for(auto tmp2 : tmp.first) cerr << ANS[tmp2] << " ";
        cerr << endl;
        for(auto tmp2 : tmp.second) cerr << ANS[tmp2] << " ";
        cerr << endl;
        cerr << endl;
    }
    */
    vector<vector<ll>> ok, ng;
    ok.resize(V.size(), vector<ll>(V[0].first.size(), 0));
    ng.resize(V.size(), vector<ll>(V[0].first.size(), V[0].first.size() + 1));
    needed++;
    for(int _ = 0; _ < needed; _++) {
        vector<vector<ll>> mid;
        mid.resize(V.size());
        for(int i = 0; i < mid.size(); i++) {
            mid[i].resize(V[0].first.size());
            for(int j = 0; j < mid[i].size(); j++) {
                mid[i][j] = (ok[i][j] + ng[i][j]) / 2;
                chmax(mid[i][j], 1LL);
                A[V[i].first[j]] = V[i].second[mid[i][j]-1];
            }
        }
        for(int i = 0; i < mid.size(); i++) {
            for(int j = 0; j < mid[i].size(); j++) {
                A[V[i].second[j]] = V[i].second[j];
            }
        }
        ask();
        for(int i = 0; i < mid.size(); i++) {
            for(int j = 0; j < mid[i].size(); j++) {
                if(C[A[V[i].first[j]]]) {
                    C[A[V[i].first[j]]]--;
                    ng[i][j] = mid[i][j];
                } else {
                    ok[i][j] = mid[i][j];
                }
            }
        }
        /*
        cerr << "midsize: " << mid.size() << endl;
        for(int i = 0; i < mid.size(); i++) {
            for(int j = 0; j < mid[i].size(); j++) {
                cerr << "{" << ok[i][j] << ", " << ng[i][j] << "} ";
            }
            cerr << endl;
        }
        */
    }
    vector<vector<ll>> ret;
    for(int i = 0; i < V.size(); i++) {
        auto tmp = g(V[i], ok[i]);
        ret.push_back(tmp);
    }
    return ret;
}

int main() {
    cin >> N;
    N = (1 << N);
    if(LOCAL) {
        ANS.resize(N);
        for(int i = 0; i < N; i++) {
            ANS[i] = i;
        }
        std::random_device seed_gen;
        std::mt19937 engine(seed_gen());
        std::shuffle(ANS.begin(), ANS.end(), engine);
        /*
        for(auto tmp : ANS) cerr << tmp << " ";
        cerr << endl;
        */
    }
    for(int i = 0; i < N; i++) {
        v.push_back({i});
    }
    for(int _ = 0; ; _++) {
        if(v.size() == 1) break;
        vector<pair<vector<ll>, vector<ll>>> V;
        for(int i = 0; i < v.size(); i += 2) {
            V.push_back({v[i], v[i+1]});
        }
        v = f(V);
    }
    printans();
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3724
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef int_fast32_t int32;
typedef int_fast64_t int64;

const int32 inf = 1e9+7;
const int32 MOD = 1000000007;
const int64 llinf = 1e18;

#define YES(n) cout << ((n) ? "YES\n" : "NO\n"  )
#define Yes(n) cout << ((n) ? "Yes\n" : "No\n"  )
#define POSSIBLE(n) cout << ((n) ? "POSSIBLE\n" : "IMPOSSIBLE\n"  )
#define ANS(n) cout << (n) << "\n"
#define REP(i,n) for(int64 i=0;i<(n);++i)
#define FOR(i,a,b) for(int64 i=(a);i<(b);i++)
#define FORR(i,a,b) for(int64 i=(a);i>=(b);i--)
#define all(obj) (obj).begin(),(obj).end()
#define rall(obj) (obj).rbegin(),(obj).rend()
#define fi first
#define se second
#define pb(a) push_back(a)
typedef pair<int32,int32> pii;
typedef pair<int64,int64> pll;

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

int32 n;
vector<int32> a;
vector<int32> c;
vector<set<int32>> large;
vector<int32> indeg;

vector<int32> topological_sort(vector<set<int32>> G, vector<int32> indegree, int32 V) {
    // トポロジカルソートを記録する配列
    vector<int32> sorted_vertices;

    // 入次数が0の頂点を発見したら、処理待ち頂点としてキューに追加する
    queue<int> que;
    for (int i = 0; i < V; i++) {
        if (indegree[i] == 0) {
            que.push(i);
        }
    }

    // キューが空になるまで、操作1~3を繰り返す
    while (que.empty() == false) {
        // キューの先頭の頂点を取り出す
        int v = que.front();
        que.pop();

        // その頂点と隣接している頂点の入次数を減らし、0になればキューに追加
        for(auto u : G[v]){
            indegree[u] -= 1;
            if (indegree[u] == 0) que.push(u);
        }
        // 頂点vを配列の末尾に追加する 
        sorted_vertices.push_back(v);
    }

    // トポロジカルソートを返す
    return sorted_vertices;
}

void query(){
  cout << "?";
  REP(i,n){
    cout << " " << a[i]+1;
  }
  cout << endl;
  REP(i,n)cin >> c[i];
  REP(i,n){
    if(i == a[i])continue;
    if(c[a[i]] == 1){
      if(large[i].count(a[i]) == 0){
        large[i].insert(a[i]);
        indeg[a[i]]++;
      }
    }else{
      if(large[a[i]].count(i) == 0){
        large[a[i]].insert(i);
        indeg[i]++;
      }
    }
  }
}

int32 pow2(int32 r){
  int32 ret = 1;
  REP(i,r)ret *= 2;
  return ret;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin >> n;
  n = pow2(n);
  a.resize(n);
  c.resize(n);
  large.resize(n);
  indeg.resize(n,0);
  REP(i,n)a[i] = (i+1)%n;
  while(true){
    query();
    vector<pii> notyet;
    vector<int32> topo = topological_sort(large,indeg,n);
    REP(i,n-1){
      if(large[topo[i]].count(topo[i+1]) == 0)notyet.emplace_back(topo[i],topo[i+1]);
    }
    // REP(v,n){
    //   for(auto u : large[v])cout << v << " " << u << endl;
    // }
    // REP(i,n)ANS(indeg[i]);
    // REP(i,n)cout << " " << topo[i];
    // cout << endl;
    if(notyet.empty()){
      vector<int32> ans(n);
      REP(i,n){
        ans[topo[i]] = i;
      }
      cout << "!";
      REP(i,n)cout << " " << ans[i] + 1;
      cout << endl;
      return 0;
    }
    a = vector<int32>(n,-1);
    vector<bool> used(n,false);
    for(auto p : notyet){
      if(a[p.fi] == -1 && !used[p.se]){
        a[p.fi] = p.se;
        used[p.se] = true;
      }else if(a[p.se] == -1 && !used[p.fi]){
        a[p.se] = p.fi;
        used[p.fi] = true;
      }
    }
    int32 j = 0;
    REP(i,n){
      if(a[i] == -1){
        while(used[j])++j;
        a[i] = j;
        ++j;
      }
    }
  }
  return 0;
}
accuracy: 0.3191489361702128
time_ms: 40
memory_kb: 4656
final_rank: 12

code_snippet: //#define NDEBUG

#pragma region cp_template

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <utility>
#include <vector>

namespace n91 {

  using i32 = std::int32_t;
  using i64 = std::int64_t;
  using u32 = std::uint32_t;
  using u64 = std::uint64_t;
  using isize = std::ptrdiff_t;
  using usize = std::size_t;

  struct rep {
    struct itr {
      usize i;
      constexpr itr(const usize i) noexcept : i(i) {}
      void operator++() noexcept { ++i; }
      constexpr usize operator*() const noexcept { return i; }
      constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
    };
    const itr f, l;
    constexpr rep(const usize f, const usize l) noexcept
      : f(std::min(f, l)), l(l) {}
    constexpr auto begin() const noexcept { return f; }
    constexpr auto end() const noexcept { return l; }
  };
  struct revrep {
    struct itr {
      usize i;
      constexpr itr(const usize i) noexcept : i(i) {}
      void operator++() noexcept { --i; }
      constexpr usize operator*() const noexcept { return i; }
      constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
    };
    const itr f, l;
    constexpr revrep(const usize f, const usize l) noexcept
      : f(l - 1), l(std::min(f, l) - 1) {}
    constexpr auto begin() const noexcept { return f; }
    constexpr auto end() const noexcept { return l; }
  };
  template <class T> auto md_vec(const usize n, const T& value) {
    return std::vector<T>(n, value);
  }
  template <class... Args> auto md_vec(const usize n, Args... args) {
    return std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
  }
  template <class T> constexpr T difference(const T& a, const T& b) noexcept {
    return a < b ? b - a : a - b;
  }
  template <class T> void chmin(T& a, const T& b) noexcept {
    if (b < a)
      a = b;
  }
  template <class T> void chmax(T& a, const T& b) noexcept {
    if (a < b)
      a = b;
  }
  template <class F> class rec_lambda {
    F f;

  public:
    rec_lambda(F&& f) : f(std::move(f)) {}
    template <class... Args> auto operator()(Args&&... args) const {
      return f(*this, std::forward<Args>(args)...);
    }
  };
  template <class F> auto make_rec(F&& f) { return rec_lambda<F>(std::move(f)); }
  template <class T> T scan() {
    T ret;
    std::cin >> ret;
    return ret;
  }
  constexpr char eoln = '\n';
  template <class T> T ceildiv(const T& l, const T& r) {
    return l / r + (l % r != 0 ? 1 : 0);
  }

} // namespace n91

#pragma endregion cp_template

namespace n91 {

  struct sorter {
    usize n;
    std::vector<usize> x;
    // x[i]: 今 i 番目の要素が p の何番目か
    std::vector<std::pair<usize, usize>> cp;
    // first < second になるように cas

    sorter(const usize m) : n(1 << m), x(n), cp() {
      for (const usize i : rep(0, n)) {
        x[i] = i;
      }
    }

    void cas(usize less, usize greater) { cp.push_back({ less, greater }); }
    void flush() {
      std::vector<usize> a(n);
      for (const auto& e : cp) {
        a[x[e.second]] = x[e.first];
        a[x[e.first]] = x[e.second];
      }
      std::cout << "?";
      for (auto e : a) {
        std::cout << " " << e + 1;
      }
      std::cout << std::endl;
      std::vector<usize> c(n);
      for (auto& e : c) {
        std::cin >> e;
      }
      for (const auto& e : cp) {
        if (c[x[e.first]] == 1) {
          std::swap(x[e.first], x[e.second]);
        }
      }
      cp.clear();
    }
    void print() {
      std::vector<usize> p(n);
      for (const usize i : rep(0, n)) {
        p[x[i]] = i;
      }
      std::cout << "!";
      for (auto e : p) {
        std::cout << " " << e + 1;
      }
      std::cout << std::endl;
    }
  };

  void main_() {
    /*
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    //*/
    const usize n = scan<usize>();
    sorter s(n);
    for (const usize i : rep(0, n)) {
      const usize swap_wi = 2 << i;
      for (const usize j : rep(0, i + 1)) {
        bool swap_f = true;
        const usize step = 1 << (i - j);
        for (const usize k : rep(0, 1 << n)) {
          if (k % swap_wi == 0) {
            swap_f = !swap_f;
          }
          if (k & step) {
            usize l = k & ~step;
            usize r = k;
            if (swap_f) {
              std::swap(l, r);
            }
            s.cas(l, r);
          }
        }
        s.flush();
      }
    }
    s.print();
  }

} // namespace n91

int main() {
  n91::main_();
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3640
final_rank: 5

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
#define all(x) (x).begin(),(x).end()

template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}
 
template<class T> inline bool chmax(T &a, T b){
    if(a<b){
        a = b;
        return true;
    }
    return false;
}

template<class T> inline bool chmin(T &a, T b){
    if(a>b){
        a = b;
        return true;
    }
    return false;
}
int n;
vector<int> question(vector<int> &a){
    cout << "? ";
    rep(i,n){
        cout << a[i+1] << " ";
    }
    cout << endl;
    vector<int> b(n+1);
    rep(i,n){
        cin >> b[i+1];
    }
    return b;
}
void answer(vector<int> &a){
    cout << "! ";
    rep(i,n){
        cout << a[i+1] << " ";
    }
    cout << endl;
}
int main(){
    int m;
    cin >> m;
    n = (1<<m);
    vector<int> p(n);
    vector<vector<int> > q;
    rep(i,n){
        p[i] = i+1;
        vector<int> t;
        t.push_back(i+1);
        q.push_back(t);
    }
    
    for(int zz=1;zz<=m;zz++){    
        vector<vector<int> > A;
        vector<vector<int> > B;
        for(int i=0;i<q.size();i+=2){
            A.push_back(q[i]);
            B.push_back(q[i+1]);
        }
        // cerr << A.size() << endl;
        // for(auto x:A){
        //     for(auto y:x){
        //         cerr << y << " " ;
        //     }
        //     cerr << endl;
        // }
        // cerr << endl;
        // cerr << B.size() << endl;
        // for(auto x:B){
        //     for(auto y:x){
        //         cerr << y << " " ;
        //     }
        //     cerr << endl;
        // }
        // cerr << endl;
        for(int j=0;j<zz;j++){
            vector<int> q(n+1);
            // sort列 A, B の比較
            
            for(int i=0;i<A.size();i++){
                int len = B[i].size();
                int Qid = B[i][len/2];
                for(auto x: A[i]){
                    q[x] = Qid;
                }

            }
            for(int i=0;i<B.size();i++){
                for(auto x:B[i]){
                    q[x] = x;
                }
            }
            auto X = question(q);
            
            vector<vector<int> > P;
            vector<vector<int> > Q;
            
            for(int i=0;i<A.size();i++){
                int len = B[i].size();
                int Qid = B[i][len/2];
                int cnt = X[Qid];
                vector<int> pp[2];
                for(int k = 0; k<A[i].size();k++){
                    if(k < cnt){
                        pp[0].push_back(A[i][k]);
                    }else{
                        pp[1].push_back(A[i][k]);
                    }
                }
                vector<int> qq[2];
                for(int k=0;k<B[i].size();k++){
                    if(k<len/2||len==1){
                        qq[0].push_back(B[i][k]);
                    }else{
                        qq[1].push_back(B[i][k]);
                    }
                }
                P.push_back(pp[0]);
                P.push_back(pp[1]); 
                Q.push_back(qq[0]);
                Q.push_back(qq[1]);
            }    
            swap(A,P);
            swap(B,Q);
        }   
        // cerr << "TEST" << endl;
        // cerr << A.size() << endl;
        // for(auto x:A){
        //     for(auto y:x){
        //         cerr << y << " " ;
        //     }
        //     cerr << endl;
        // }
        // cerr << endl;
        // cerr << B.size() << endl;
        // for(auto x:B){
        //     for(auto y:x){
        //         cerr << y << " " ;
        //     }
        //     cerr << endl;
        // }
        // cerr << endl;
        
        vector<vector<int> > qqq;
        for(int k=0;k<(n)/(1<<zz);k++){
            vector<int> qq;
            for(int i=0;i<(1<<(zz));i++){
                // i + k*(1<<zz) 
                for(auto x:A[i + k*(1<<(zz))]){
                    qq.push_back(x);
                }
                for(auto x:B[i + k*(1<<(zz))]){
                    qq.push_back(x);
                }
            }
            qqq.push_back(qq);
        }
        swap(q,qqq);
    }
    vector<int> pppp(n+1);
    for(int i=0;i<q[0].size();i++){
        pppp[q[0][i]] = i+ 1;
    }
    answer(pppp);
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3676
final_rank: 7

code_snippet: //#define _GLIBCXX_DEBUG
//#include "atcoder/all"
//using namespace atcoder;
#include <bits/stdc++.h>
#define int long long
#define ll long long
using ull = unsigned long long;
using namespace std;
#define dump(x)                             \
    if (dbg) {                              \
        cerr << #x << " = " << (x) << endl; \
    }
#define overload4(_1, _2, _3, _4, name, ...) name
#define FOR1(n) for (ll i = 0; i < (n); ++i)
#define FOR2(i, n) for (ll i = 0; i < (n); ++i)
#define FOR3(i, a, b) for (ll i = (a); i < (b); ++i)
#define FOR4(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FORR(i, a, b) for (int i = (a); i <= (b); ++i)
#define bit(n, k) (((n) >> (k)) & 1) /*nのk bit目*/
namespace mydef {
const int INF = 1ll << 60;
const int MOD = 1e9 + 7;
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;
}
void Yes(bool flag = true) {
    if (flag)
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}
void No(bool flag = true) {
    Yes(!flag);
}
void YES(bool flag = true) {
    if (flag)
        cout << "YES" << endl;
    else
        cout << "NO" << endl;
}
void NO(bool flag = true) {
    YES(!flag);
}
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T& val) {
    std::fill((T*)array, (T*)(array + N), val);
}
bool dbg = true;
}  // namespace mydef
using namespace mydef;
#define pb push_back
//#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(), (v).end()
#define SZ(x) ((int)(x).size())
#define vi vector<int>
#define vvi vector<vector<int>>
#define vp vector<pair<int, int>>
#define vvp vector<vector<pair<int, int>>>
#define pi pair<int, int>
//#define P pair<int, int>
//#define V vector<int>
//#define S set<int>
#define asn ans

vi query;
int N;

template <typename T>
struct edge {
    int to, id;
    T cost;
    edge(int to) : to(to), id(-1), cost(1) {}
    edge(int to, T cost) : to(to), id(-1), cost(cost) {}
    edge(int to, T cost, int id) : to(to), id(id), cost(cost) {}
    operator int() const { return to; }
    /*
        edge& operator=(const int& x) {
            to = x;
            return *this;
        }
        */
};
template <typename T>
class Graph : public vector<vector<edge<T>>> {
    //--------Basic--------
private:
    using Edge = edge<T>;
    int M;  //M:辺の数
    bool undirected = false;
    bool directed = false;
    bool unweighted = false;
    bool weighted = false;
    bool tree = false;
    //
public:
    vector<int> A, B;
    vector<T> C;
    //
public:
    Graph() = default;
    //unweighted
    void add_edge_undirected(int u, int v, int id = -1) {
        assert(!directed);
        assert(!weighted);
        undirected = true;
        unweighted = true;
        (*this)[u].emplace_back(Edge{v, 1, id});
        (*this)[v].emplace_back(Edge{u, 1, id});
    }
    void build_undirected(int m) {
        assert(!(*this).empty());
        assert(!directed);
        assert(!weighted);
        undirected = true;
        unweighted = true;
        M = m;
        A.resize(m);
        B.resize(m);
        for (int i = 0; i < m; i++) {
            int u, v;
            cin >> u >> v;
            u--;
            v--;
            A[i] = u;
            B[i] = v;
            (*this)[u].emplace_back(Edge{v, 1, i});
            (*this)[v].emplace_back(Edge{u, 1, i});
        }
    }
    void build_undirected(int n, int m) {
        (*this).resize(n);
        build_undirected(m);
    }
    void add_edge_directed(int u, int v, int id = -1) {
        assert(!undirected);
        assert(!weighted);
        directed = true;
        unweighted = true;
        (*this)[u].emplace_back(Edge{v, 1, id});
    }
    void build_directed(int m) {
        assert(!(*this).empty());
        assert(!undirected);
        assert(!weighted);
        directed = true;
        unweighted = true;
        M = m;
        A.resize(M);
        B.resize(M);
        for (int i = 0; i < m; i++) {
            int u, v;
            cin >> u >> v;
            u--;
            v--;
            A[i] = u;
            B[i] = v;
            (*this)[u].emplace_back(Edge{v, 1, i});
        }
    }
    void build_directed(int n, int m) {
        (*this).resize(n);
        build_directed(m);
    }
    //weighed
    void add_edge_undirected_weighed(int u, int v, T cost, int id = -1) {
        assert(!directed);
        assert(!unweighted);
        undirected = true;
        weighted = true;
        (*this)[u].emplace_back(Edge{v, cost, id});
        (*this)[v].emplace_back(Edge{u, cost, id});
    }
    void build_undirected_weighted(int m) {
        assert(!(*this).empty());
        assert(!directed);
        assert(!unweighted);
        undirected = true;
        weighted = true;
        M = m;
        A.resize(m);
        B.resize(m);
        C.resize(m);
        for (int i = 0; i < m; i++) {
            int u, v;
            T cost;
            cin >> u >> v >> cost;
            u--;
            v--;
            A[i] = u;
            B[i] = v;
            C[i] = cost;
            (*this)[u].emplace_back(Edge{v, cost, i});
            (*this)[v].emplace_back(Edge{u, cost, i});
        }
    }
    void build_undirected_weighted(int n, int m) {
        (*this).resize(n);
        build_undirected_weighted(m);
    }
    void add_edge_directed_weighted(int u, int v, T cost, int id = -1) {
        assert(!undirected);
        assert(!unweighted);
        directed = true;
        weighted = true;
        (*this)[u].emplace_back(Edge{v, cost, id});
    }
    void build_directed_weighted(int m) {
        assert(!(*this).empty());
        assert(!undirected);
        assert(!unweighted);
        directed = true;
        weighted = true;
        M = m;
        A.resize(m);
        B.resize(m);
        C.resize(m);
        for (int i = 0; i < m; i++) {
            int u, v;
            T cost;
            cin >> u >> v >> cost;
            u--;
            v--;
            A[i] = u;
            B[i] = v;
            C[i] = cost;
            (*this)[u].emplace_back(Edge{v, cost, i});
        }
    }
    void build_directed_weighted(int n, int m) {
        (*this).resize(n);
        build_directed_weighted(m);
    }
    void build(vector<vector<int>> G) {
        int N = G.size();
        (*this).resize(N);
        for (int i = 0; i < N; i++) {
            for (auto& x : G[i]) {
                add_edge_directed(i, x);
            }
        }
    }
    //tree
    void istree() {
        tree = true;
    }
    void build_tree(int n) {
        istree();
        build_undirected(n, n - 1);
    }
    void build_tree_weighted(int n) {
        istree();
        build_undirected_weighted(n, n - 1);
    }
    //print state
    void state() {
        cerr << endl
             << "Print State" << endl
             << "Edge :" << endl
             << "    Directed   : " << (directed ? "Yes" : "No") << endl
             << "    Undirected : " << (undirected ? "Yes" : "No") << endl
             << "    Weighted   : " << (weighted ? "Yes" : "No") << endl
             << "    Unweighted : " << (unweighted ? "Yes" : "No") << endl
             << "    Tree       : " << (tree ? "Yes" : "No") << endl
             << "Test" << endl
             << "    test_bipartite(verified) : Yes" << endl
             << "Usable Functions : Graph" << endl
             << "    Dijkstra(verified) : Yes" << endl
             << "    Warshall–Floyd(verified) : Yes" << endl
             << "    Kruskal(verified) : Yes" << endl
             << "    TopologicalSort(verified) : Yes" << endl
             << "    StronglyConnectedComponent(unverified): " << (StronglyConnectedComponent_ready ? "Yes" : "No") << endl
             << "Usable Funcitons : Tree" << endl
             << "    ReRooting(verified) : Yes" << endl;
    }
    //
    //--------union-find tree--------
    struct UnionFind {
        vector<int> data;
        UnionFind(int n) {
            data.assign(n, -1);
        }
        bool unite(int x, int y) {
            x = root(x), y = root(y);
            if (x == y)
                return (false);
            if (data[x] > data[y])
                swap(x, y);
            data[x] += data[y];
            data[y] = x;
            return (true);
        }
        int root(int k) {
            if (data[k] < 0)
                return (k);
            return (data[k] = root(data[k]));
        }
        bool same(int x, int y) {
            return root(x) == root(y);
        }
        int size(int k) {
            return (-data[root(k)]);
        }
    };
    //
    //--------test_bipartite--------
    //verified
public:
    bool test_bipartite() {
        int N = (*this).size();
        UnionFind uf(N * 2);
        for (int i = 0; i < N; i++) {
            for (auto& e : (*this)[i]) {
                uf.unite(i, e.to + N);
                uf.unite(i + N, e.to);
            }
        }
        for (int i = 0; i < N; i++) {
            if (uf.same(i, i + N))
                return false;
        }
        return true;
    }
    //
    //--------reverse--------
public:
    void reverse() {
        int N = (*this).size();
        vector<pair<int, Edge>> V;
        V.reserve(M);
        for (int i = 0; i < N; i++) {
            for (auto& e : (*this)[i]) {
                V.emplace_back(make_pair(i, e));
            }
        }
        (*this).erase((*this).begin(), (*this).end());
        (*this).resize(N);
        for (auto& p : V)
            (*this)[p.second.to].emplace_back(Edge{p.first, p.second.cost, p.second.id});
    }
    //
    //--------Dijkstra--------
    //verified
public:
    //pair<vector<T>, vector<int>> Dijkstra(int s) {
    vector<T> Dijkstra(int s) {
        const T INF = numeric_limits<T>::max() / 5;
        using P = pair<T, int>;
        int N = (*this).size();
        vector<T> dist(N, INF);
        //vector<int> bef(N, -1);
        priority_queue<P, vector<P>, greater<P>> que;
        dist[s] = 0;
        que.emplace(dist[s], s);
        while (!que.empty()) {
            P p = que.top();
            que.pop();
            int now = p.second;
            if (dist[now] < p.first)
                continue;
            for (auto& p : (*this)[now]) {
                int nxt = p.to;
                T cost = p.cost;
                if (dist[nxt] > dist[now] + cost) {
                    dist[nxt] = dist[now] + cost;
                    //bef[nxt] = now;
                    que.emplace(dist[nxt], nxt);
                }
            }
        }
        return dist;
        //return make_pair(dist, bef);
    }
    //
    //
    //--------Warshall–Floyd--------
    //verified
public:
    vector<vector<T>> WarshallFloyd() {
        int N = (*this).size();
        const T INF = numeric_limits<T>::max() / 3;
        vector<vector<T>> ret(N, vector<T>(N, INF));
        for (int i = 0; i < N; i++) {
            for (auto& e : (*this)[i]) {
                ret[i][e.to] = e.cost;
            }
            ret[i][i] = 0;
        }
        for (int k = 0; k < N; k++) {
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (ret[i][j] > ret[i][k] + ret[k][j])
                        ret[i][j] = ret[i][k] + ret[k][j];
                }
            }
        }
        return ret;
    }
    //
    //
    //--------Kruskal--------
    //verified
private:
    vector<int> Kruskal_data;
    bool Kruskal_unite(int x, int y) {
        x = Kruskal_root(x), y = Kruskal_root(y);
        if (x == y)
            return (false);
        if (Kruskal_data[x] > Kruskal_data[y])
            swap(x, y);
        Kruskal_data[x] += Kruskal_data[y];
        Kruskal_data[y] = x;
        return (true);
    }
    int Kruskal_root(int k) {
        if (Kruskal_data[k] < 0)
            return (k);
        return (Kruskal_data[k] = Kruskal_root(Kruskal_data[k]));
    }
    bool Kruskal_same(int x, int y) {
        return Kruskal_root(x) == Kruskal_root(y);
    }
    int Kruskal_size(int k) {
        return (-Kruskal_data[Kruskal_root(k)]);
    }
    //
public:
    template <class Compare = less<T>>
    pair<T, vector<bool>> Kruskal(bool flag = false) {
        struct edge2 {
            int from, to;
            T cost;
            bool used;
            int id;
            edge2(int from, int to, T cost, int id) : from(from), to(to), cost(cost), used(false), id(id) {}
        };
        vector<edge2> edges;
        int N = (*this).size();
        Kruskal_data.assign(N, -1);
        for (int i = 0; i < (int)(*this).size(); i++) {
            auto& V = (*this)[i];
            for (auto& e : V) {
                edges.emplace_back(i, e.to, e.cost, e.id);
            }
        }
        sort(edges.begin(), edges.end(), [](const edge2& a, const edge2& b) {
            return Compare()(a.cost, b.cost);
        });
        T ret = 0;
        vector<bool> V;
        if (flag)
            V.resize(M, false);
        for (auto& e : edges) {
            if (Kruskal_unite(e.from, e.to)) {
                ret += e.cost;
                e.used = true;
            }
        }
        if (flag)
            for (auto& e : edges) {
                assert(e.id >= 0 && e.id < M);
                if (e.used)
                    V[e.id] = true;
            }
        if (N == Kruskal_size(0))
            return make_pair(ret, V);
        else
            return make_pair(-1, V);
    }
    //
    //--------StronglyConnectedComponent--------
    //Unverified
public:
    vector<vector<int>> SCC_R, SCC_T;
    //
private:
    bool StronglyConnectedComponent_ready = false;
    vector<int> SCC_cmp, SCC_ord;
    vector<bool> SCC_used;
    //
public:
    int Gbuild_SCC() {
        cerr << "Please Verify" << endl;
        assert(!undirected);
        assert(directed);
        int N = (*this).size();
        SCC_R.resize(N);
        for (int i = 0; i < N; i++) {
            for (auto& x : (*this)[i]) {
                SCC_R[x].emplace_back(i);
            }
        }
        SCC_cmp.resize(N);
        fill(SCC_cmp.begin(), SCC_cmp.end(), -1);
        SCC_used.resize(N);
        fill(SCC_used.begin(), SCC_used.end(), false);
        StronglyConnectedComponent_ready = true;
        return build_StronglyConnectedComponent_init();
    }
    int SCC(int k) {
        assert(StronglyConnectedComponent_ready);
        return SCC_cmp[k];
    }
    //
private:
    void build_StronglyConnectedComponent_dfs(int now) {
        if (SCC_used[now])
            return;
        SCC_used[now] = true;
        for (auto nxt : (*this)[now])
            build_StronglyConnectedComponent_dfs(nxt);
        SCC_ord.emplace_back(now);
    }
    void build_StronglyConnectedComponent_rdfs(int now, int count) {
        if (SCC_cmp[now] != -1)
            return;
        SCC_cmp[now] = count;
        for (auto to : SCC_R[now])
            build_StronglyConnectedComponent_rdfs(to, count);
    }
    int build_StronglyConnectedComponent_init() {
        int n = (int)(*this).size();
        for (int i = 0; i < n; i++)
            build_StronglyConnectedComponent_dfs(i);
        std::reverse(SCC_ord.begin(), SCC_ord.end());
        int group = 0;
        for (auto& i : SCC_ord) {
            if (SCC_cmp[i] == -1) {
                build_StronglyConnectedComponent_rdfs(i, group);
                group++;
            }
        }
        SCC_T.resize(group);
        for (int i = 0; i < n; i++) {
            for (auto& to : (*this)[i]) {
                int s = SCC_cmp[i], t = SCC_cmp[to];
                if (s != t)
                    SCC_T[s].emplace_back(t);
            }
        }
        return group;
    }
    //
    //
    //
    //--------TopologicalSort--------
    //verified
public:
    vector<int> TopologicalSort() {
        assert(!undirected);
        int N = (*this).size();
        vector<int> deg(N);
        for (auto& V : (*this))
            for (auto& e : V)
                deg[e.to]++;
        queue<int> st;
        for (int i = 0; i < N; i++)
            if (deg[i] == 0)
                st.push(i);
        vector<int> ret;
        ret.reserve(N);
        while (!st.empty()) {
            auto x = st.front();
            st.pop();
            ret.emplace_back(x);
            if (st.empty()) {
                query[x] = x;
            } else {
                query[x] = st.front();
            }
            for (auto& e : (*this)[x])
                if (--deg[e.to] == 0)
                    st.push(e.to);
        }
        return ret;
    }
    //
    //
    //--------Tree--------
    //
    //
    //--------ReRooting--------
public:
    template <typename sum_t>
    pair<vector<sum_t>, vector<vector<sum_t>>>
    Tbuild_ReRooting(
        const function<sum_t(sum_t, sum_t)> f,
        const function<sum_t(sum_t, Edge)> gg,
        sum_t ident) {
        assert(tree);
        int N = (*this).size();
        vector<sum_t> subdp(N, ident), dp(N, ident);
        vector<vector<sum_t>> g_dp(N), g_ndp(N), memo(N);
        vector<vector<bool>> seen(N);
        for (int i = 0; i < N; i++) {
            int S = (*this)[i].size();
            g_dp[i].resize(S, ident);
            g_ndp[i].resize(S, ident);
            memo[i].resize(S);
            seen[i].resize(S, false);
        }
        stack<int> stk;
        stk.push(0);
        vector<int> par(N), ord(N);
        int index = 0;
        par[0] = -1;
        while (!stk.empty()) {
            int node = stk.top();
            stk.pop();
            ord[index++] = node;
            for (auto& e : (*this)[node]) {
                if (e.to == par[node])
                    continue;
                stk.push(e.to);
                par[e.to] = node;
            }
        }
        for (int k = ord.size() - 1; k >= 0; k--) {
            int idx = ord[k];
            for (int i = 0; i < (int)((*this)[idx].size()); i++) {
                auto& e = (*this)[idx][i];
                if (e.to == par[idx])
                    continue;
                if (!seen[idx][i]) {
                    memo[idx][i] = gg(subdp[e.to], e);
                    seen[idx][i] = true;
                }
                subdp[idx] = f(subdp[idx], memo[idx][i]);
            }
        }
        vector<sum_t> top(N, ident);
        for (int k = 0; k < (int)(ord.size()); k++) {
            int idx = ord[k];
            sum_t buff{ident};
            for (int i = 0; i < (int)((*this)[idx].size()); i++) {
                auto& e = (*this)[idx][i];
                g_ndp[idx][i] = buff;
                if (!seen[idx][i]) {
                    memo[idx][i] = gg(par[idx] == e.to ? top[idx] : subdp[e.to], e);
                    seen[idx][i] = true;
                }
                g_dp[idx][i] = memo[idx][i];
                buff = f(buff, g_dp[idx][i]);
            }
            dp[idx] = buff;
            buff = ident;
            for (int i = (*this)[idx].size() - 1; i >= 0; i--) {
                auto& e = (*this)[idx][i];
                if (e.to != par[idx])
                    top[e.to] = f(g_ndp[idx][i], buff);
                g_ndp[idx][i] = f(g_ndp[idx][i], buff);
                buff = f(buff, g_dp[idx][i]);
            }
        }
        return make_pair(dp, memo);
    }
    //
    //
    //
    //TODO:lca,centroid,diameter,hl-decomposition
};
//グローバルでの使用のみ想定

Graph<int> G;
int NN;

void solve() {
    NN = (1 << N);
    G.resize(NN);
    query.resize(NN);
    int TIME = 60;
    while (TIME--) {
        //queryを計算
        auto A = G.TopologicalSort();

        //queryをチェック
        bool flag = true;
        for (int i = 0; i < NN; i++) {
            if (query[i] != i)
                flag = false;
        }

        if (flag) {
            //答えを出力
            vi ans(NN);
            for (int i = 0; i < NN; i++) {
                ans[A[i]] = i;
            }
            cout << "!";
            for (auto& x : ans)
                cout << " " << x + 1;
            cout << endl;
            return;
        }

        cout << "?";
        for (auto& x : query)
            cout << " " << x + 1;
        cout << endl;

        vi C(NN);
        for (int i = 0; i < NN; i++) {
            cin >> C[i];
        }

        for (int i = 0; i < NN; i++) {
            if (i != query[i]) {
                if (C[query[i]] == 1) {
                    G.add_edge_directed(i, query[i]);
                } else {
                    G.add_edge_directed(query[i], i);
                }
            }
        }
    }
    assert(false);
}

signed main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    cin >> N;


    solve();
    return 0;
}
accuracy: 0.3191489361702128
time_ms: 40
memory_kb: 3404
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using uint = unsigned;
using pcc = pair<char, char>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
using tuplis = array<ll, 3>;
template<class T> using pq = priority_queue<T, vector<T>, greater<T>>;
const ll LINF=0x1fffffffffffffff;
const ll MINF=0x7fffffffffff;
const int INF=0x3fffffff;
const int MOD=1000000007;
const int MODD=998244353;
const ld DINF=numeric_limits<ld>::infinity();
const ld EPS=1e-9;
const ld PI=3.1415926535897932;
const ll dx[] = {0, 1, 0, -1, 1, -1, 1, -1};
const ll dy[] = {1, 0, -1, 0, 1, 1, -1, -1};
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep4(i,a,b,c) for(ll i=(a)+((b)-(a)-1)/(c)*(c);i>=(a);i-=c)
#define rrep(...) overload4(__VA_ARGS__,rrep4,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define each1(i,a) for(auto&&i:a)
#define each2(x,y,a) for(auto&&[x,y]:a)
#define each3(x,y,z,a) for(auto&&[x,y,z]:a)
#define each(...) overload4(__VA_ARGS__,each3,each2,each1)(__VA_ARGS__)
#define all1(i) begin(i),end(i)
#define all2(i,a) begin(i),begin(i)+a
#define all3(i,a,b) begin(i)+a,begin(i)+b
#define all(...) overload3(__VA_ARGS__,all3,all2,all1)(__VA_ARGS__)
#define rall1(i) (i).rbegin(),(i).rend()
#define rall2(i,k) (i).rbegin(),(i).rbegin()+k
#define rall3(i,a,b) (i).rbegin()+a,(i).rbegin()+b
#define rall(...) overload3(__VA_ARGS__,rall3,rall2,rall1)(__VA_ARGS__)
#define sum(...) accumulate(all(__VA_ARGS__),0LL)
#define dsum(...) accumulate(all(__VA_ARGS__),0.0L)
#define Msum(...) accumulate(all(__VA_ARGS__),0_M)
#define elif else if
#define unless(a) if(!(a))
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;in(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;in(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;in(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;in(__VA_ARGS__)
#define Sort(a) sort(all(a))
#define Rev(a) reverse(all(a))
#define Uniq(a) sort(all(a));a.erase(unique(all(a)),end(a))
#define vec(type,name,...) vector<type>name(__VA_ARGS__)
#define VEC(type,name,size) vector<type>name(size);in(name)
#define vv(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));in(name)
#define vvv(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
template<class T> auto min(const T& a){ return *min_element(all(a)); }
template<class T> auto max(const T& a){ return *max_element(all(a)); }
inline ll popcnt(ull a){ return __builtin_popcountll(a); }
ll gcd(ll a, ll b){ while(b){ ll c = b; b = a % b; a = c; } return a; }
ll lcm(ll a, ll b){ if(!a || !b) return 0; return a * b / gcd(a, b); }
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
template<class T> bool chmin(T& a, const T& b){ if(a > b){ a = b; return 1; } return 0; }
template<class T> bool chmax(T& a, const T& b){ if(a < b){ a = b; return 1; } return 0; }
template<class T, class U> bool chmin(T& a, const U& b){ if(a > T(b)){ a = b; return 1; } return 0; }
template<class T, class U> bool chmax(T& a, const U& b){ if(a < T(b)){ a = b; return 1; } return 0; }
vector<ll> iota(ll n, ll begin = 0){ vector<ll> a(n); iota(a.begin(), a.end(), begin); return a; }
vector<pll> factor(ull x){ vector<pll> ans; for(ull i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
map<ll,ll> factor_map(ull x){ map<ll,ll> ans; for(ull i = 2; i * i <= x; i++) if(x % i == 0){ ans[i] = 1; while((x /= i) % i == 0) ans[i]++; } if(x != 1) ans[x] = 1; return ans; }
vector<ll> divisor(ull x){ vector<ll> ans; for(ull i = 1; i * i <= x; i++) if(x % i == 0) ans.push_back(i); rrep(ans.size() - (ans.back() * ans.back() == x)) ans.push_back(x / ans[i]); return ans; }
template<class T> unordered_map<T, ll> press(vector<T> a){ Uniq(a); unordered_map<T, ll> ans; rep(a.size()) ans[a[i]] = i; return ans; }
template<class T> map<T, ll> press_map(vector<T> a){ Uniq(a); map<T, ll> ans; rep(a.size()) ans[a[i]] = i; return ans; }
int scan(){ return getchar(); }
void scan(int& a){ scanf("%d", &a); }
void scan(unsigned& a){ scanf("%u", &a); }
void scan(long& a){ scanf("%ld", &a); }
void scan(long long& a){ scanf("%lld", &a); }
void scan(unsigned long long& a){ scanf("%llu", &a); }
void scan(char& a){ do{ a = getchar(); }while(a == ' ' || a == '\n'); }
void scan(float& a){ scanf("%f", &a); }
void scan(double& a){ scanf("%lf", &a); }
void scan(long double& a){ scanf("%Lf", &a); }
void scan(vector<bool>& a){ for(unsigned i = 0; i < a.size(); i++){ int b; scan(b); a[i] = b; } }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto&& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto&& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto&& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto&& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){ scan(head); in(tail...); }
void print(){ putchar(' '); }
void print(bool a){ printf("%d", a); }
void print(int a){ printf("%d", a); }
void print(unsigned a){ printf("%u", a); }
void print(long a){ printf("%ld", a); }
void print(long long a){ printf("%lld", a); }
void print(unsigned long long a){ printf("%llu", a); }
void print(char a){ printf("%c", a); }
void print(char a[]){ printf("%s", a); }
void print(const char a[]){ printf("%s", a); }
void print(float a){ printf("%.15f", a); }
void print(double a){ printf("%.15f", a); }
void print(long double a){ printf("%.15Lf", a); }
void print(const string& a){ for(auto&& i : a) print(i); }
template<class T> void print(const complex<T>& a){ if(a.real() >= 0) print('+'); print(a.real()); if(a.imag() >= 0) print('+'); print(a.imag()); print('i'); }
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ print(p.first); putchar(' '); print(p.second); }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ putchar(' '); print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
#ifdef DEBUG
inline ll __lg(ull __n){ return sizeof(ull) * __CHAR_BIT__  - 1 - __builtin_clzll(__n); }
#define debug(...) { print(#__VA_ARGS__); print(":"); out(__VA_ARGS__); }
#else
#define debug(...) void(0)
#endif
int first(bool i = true){ return out(i?"first":"second"); }
int First(bool i = true){ return out(i?"First":"Second"); }
int yes(bool i = true){ return out(i?"yes":"no"); }
int Yes(bool i = true){ return out(i?"Yes":"No"); }
int No(){ return out("No"); }
int YES(bool i = true){ return out(i?"YES":"NO"); }
int NO(){ return out("NO"); }
int Yay(bool i = true){ return out(i?"Yay!":":("); }
int possible(bool i = true){ return out(i?"possible":"impossible"); }
int Possible(bool i = true){ return out(i?"Possible":"Impossible"); }
int POSSIBLE(bool i = true){ return out(i?"POSSIBLE":"IMPOSSIBLE"); }
void Case(ll i){ printf("Case #%lld: ", i); }


vector<ll>A;
vector<ll> query(const vector<ll>&a,const vector<ll>&s){
    vector<ll>q(a.size());
    rep(a.size())q[s[i]]=s[a[i]]+1;
    print("? ");
    out(q);
    fflush(stdout);
    #ifdef DEBUG
    vec(ll,c,a.size());
    rep(a.size())if(A[i]<A[q[i]-1])c[q[i]-1]++;
    #else
    VEC(ll,c,a.size());
    #endif
    vec(ll,d,a.size());
    rep(a.size())d[i]=c[s[i]];
    return d;
}
void answer(vector<ll>a){
    vector<ll>ans(a.size());
    rep(a.size())ans[a[i]]=i+1;
    print("! ");
    out(ans);
    fflush(stdout);
    #ifdef DEBUG
    rep(a.size())assert(A[i]==ans[i]-1);
    #endif
    exit(0);
}
signed main(){
#ifdef DEBUG
ll n=10;
A=iota(1<<n);
shuffle(all(A),random_device{});
#else
    LL(n);
#endif
    auto a=iota(1<<n);
    rep(n){
        vec(ll,cnt,1<<n);
        rrep(j,i){
            vec(ll,q,1<<n);
            rep(begin,0,1<<n,2<<i){
                const ll end=begin+(2<<i),cen=begin+(1<<i);
                rep(at,cen,end){
                    q[at]=at;
                    if(at>>i&1&&(at&(2<<j)-1)==(1<<j)){
                        const ll front=cnt[at-(1<<j)],back=at+(1<<j)==end?1<<i:cnt[at+(1<<j)];
                        rep(i,front,back)q[begin+i]=at;
                    }
                }
            }
            q=query(q,a);
            rep(begin,0,1<<n,2<<i){
                const ll end=begin+(2<<i),cen=begin+(1<<i);
                rep(at,cen,end){
                    if(at>>i&1&&(at&(2<<j)-1)==(1<<j)){
                        rep(i,at,at+(1<<j))cnt[i]+=q[at];
                    }
                }
            }
        }
        vec(ll,q,1<<n);
        rep(j,1<<n)q[j]=(j>>i^1)<<i;
        q=query(q,a);
        rep(j,1<<i,1<<n,2<<i)cnt[j]=q[j];
        rep(begin,0,1<<n,2<<i){
            const ll end=begin+(2<<i),cen=begin+(1<<i);
            ll at=cen;
            vec(ll,b,0);
            rep(j,1<<i){
                while(at<end&&cnt[at]==j){
                    b.push_back(a[at]);
                    at++;
                }
                b.push_back(a[begin+j]);
                while(at<end&&cnt[at]==j+1){
                    b.push_back(a[at]);
                    at++;
                }
            }
            rep(j,2<<i)a[begin+j]=b[j];
        }
    }
    answer(a);
}
accuracy: 1
time_ms: 50
memory_kb: 3644
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll=long long;
#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

pi readpi(int off=0){
	int a,b;cin>>a>>b;
	return pi(a+off,b+off);
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
ll mask(int i){
	return (ll(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
	static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
	#endif
	return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
void myshuffle(vc<t>&a){
	rep(i,si(a))swap(a[i],a[rand_int(0,i)]);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

vvc<int> readGraph(int n,int m){
	vvc<int> g(n);
	rep(i,m){
		int a,b;
		cin>>a>>b;
		//sc.read(a,b);
		a--;b--;
		g[a].pb(b);
		g[b].pb(a);
	}
	return g;
}

vvc<int> readTree(int n){
	return readGraph(n,n-1);
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	
	int n;cin>>n;
	int s=1<<n;
	vi idx(s);iota(all(idx),0);
	vvc<pi> a;
	//x->small
	//y->large
	auto waf=[&](int i,int x,int y){
		if(si(a)<i+1)a.resize(i+1);
		a[i].eb(x,y);
	};
	for(int w=2;w<=s;w*=2){
		int off=si(a);
		bool mode=false;
		for(int i=0;i<s;i+=w){
			int head=off;
			for(int h=w/2;h>=1;h/=2){
				for(int j=i;j<i+w;j+=2*h){
					for(int k=j;k<j+h;k++){
						if(!mode)waf(head,k,k+h);
						else waf(head,k+h,k);
					}
				}
				head++;
			}
			mode^=1;
		}
	}
	int L=si(a);
	rep(i,L){
		assert(si(a[i])==s/2);
		vi u(s);
		for(auto w:a[i]){
			u[w.a]++;
			u[w.b]++;
		}
		assert(u==vi(s,1));
	}
	
	//cerr<<L<<endl;
	
	#ifdef LOCAL
	rep(_,100){
		vi p(s);
		iota(all(p),0);
		myshuffle(p);
		rep(i,L){
			for(auto w:a[i]){
				if(p[w.a]>p[w.b]){
					swap(p[w.a],p[w.b]);
				}
			}
		}
		assert(p==idx);
	}
	#endif
	
	rep(i,L){
		vi val(s);iota(all(val),0);
		for(auto w:a[i]){
			swap(val[idx[w.a]],val[idx[w.b]]);
		}
		for(auto&v:val)v++;
		cout<<"? ";
		print(val);
		cout.flush();
		vi c=readvi(s);
		for(auto w:a[i]){
			if(c[idx[w.a]]){
				swap(idx[w.a],idx[w.b]);
			}
		}
	}
	
	cout<<"! ";
	vi ans(s);
	rep(i,s)ans[idx[i]]=i+1;
	print(ans);
	cout.flush();
}
accuracy: 1
time_ms: 50
memory_kb: 3696
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
const ll MOD=1000000007;
//const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T,typename U>T & chmax(T &a,const U &b){if(a<b){a=b;} return a;}
template<typename T,typename U>T & chmin(T &a,const U &b){if(b<a){a=b;} return a;}

int middle(int lf,int rg){return (rg-lf)/2+lf;}

int main(){
  
  int N;
  cin>>N;
  int sz=1<<N;
  vector<int> A(sz),C(sz),ans(sz),lw(sz),hg(sz),tmp(sz);
  auto ask=
    [&](){
      for(int i=0;i<sz;i++){tmp[ans[i]]=ans[A[i]]+1;}
      cout<<"? "<<tmp<<endl;
      cin>>tmp;
      for(int i=0;i<sz;i++){C[i]=tmp[ans[i]];}
    };
  for(int i=0;i<sz;i++){ans[i]=i;}
  for(int i=1,L=2;i<sz;i<<=1,L<<=1){
    for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
      for(int j=lf;j<mid;j++){lw[j]=mid; hg[j]=rg;}
    }
    for(int dif=i;dif>0;dif>>=1){
      for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
        for(int j=lf;j<mid;j++){
          A[j]=lw[j]+dif/2;
          A[j+i]=j;
        }
      }
      ask();
      for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
        for(int j=lf;j<mid;j++){
          if(C[A[j]]){C[A[j]]--; hg[j]=A[j];}
          else{lw[j]=A[j];}
        }
      }
    }
    for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
      for(int j=lf,k=mid,idx=lf;idx<rg;){
        while(j<mid && hg[j]<=k){tmp[idx++]=ans[j++];}
        if(k<rg){tmp[idx++]=ans[k++];}
      }
    }
    ans=tmp;
  }
  for(int i=0;i<sz;i++){tmp[ans[i]]=i+1;}
  cout<<"! "<<tmp<<endl;
cout<<"uku";
cout<<flush;
  
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3628
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
const ll MOD=1000000007;
//const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T,typename U>T & chmax(T &a,const U &b){if(a<b){a=b;} return a;}
template<typename T,typename U>T & chmin(T &a,const U &b){if(b<a){a=b;} return a;}

int middle(int lf,int rg){return (rg-lf)/2+lf;}

int main(){
  
  int N;
  cin>>N;
  int sz=1<<N;
  vector<int> A(sz),C(sz),ans(sz),lw(sz),hg(sz),tmp(sz);
  auto ask=
    [&](){
      for(int i=0;i<sz;i++){tmp[ans[i]]=ans[A[i]]+1;}
      cout<<"? "<<tmp<<endl;
      cin>>tmp;
      for(int i=0;i<sz;i++){C[i]=tmp[ans[i]];}
    };
  for(int i=0;i<sz;i++){ans[i]=i;}
  for(int i=1,L=2;i<sz;i<<=1,L<<=1){
    for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
      for(int j=lf;j<mid;j++){lw[j]=mid; hg[j]=rg;}
    }
    for(int dif=i;dif>0;dif>>=1){
      for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
        for(int j=lf;j<mid;j++){
          A[j]=lw[j]+dif/2;
          A[j+i]=j;
        }
      }
      ask();
      for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
        for(int j=lf;j<mid;j++){
          if(C[A[j]]){C[A[j]]--; hg[j]=A[j];}
          else{lw[j]=A[j];}
        }
      }
    }
    for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
      for(int j=lf,k=mid,idx=lf;idx<rg;){
        while(j<mid && hg[j]<=k){tmp[idx++]=ans[j++];}
        if(k<rg){tmp[idx++]=ans[k++];}
      }
    }
    ans=tmp;
  }
  for(int i=0;i<sz;i++){tmp[ans[i]]=i+1;}
  cout<<"! "<<tmp<<endl;
cout<<"uku";
  
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3632
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
const ll MOD=1000000007;
//const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T,typename U>T & chmax(T &a,const U &b){if(a<b){a=b;} return a;}
template<typename T,typename U>T & chmin(T &a,const U &b){if(b<a){a=b;} return a;}

int middle(int lf,int rg){return (rg-lf)/2+lf;}

int main(){
  
  int N;
  cin>>N;
  int sz=1<<N;
  vector<int> A(sz),C(sz),ans(sz),lw(sz),hg(sz),tmp(sz);
  auto ask=
    [&](){
      for(int i=0;i<sz;i++){tmp[ans[i]]=ans[A[i]]+1;}
      cout<<"? "<<tmp<<endl;
      cin>>tmp;
      for(int i=0;i<sz;i++){C[i]=tmp[ans[i]];}
    };
  for(int i=0;i<sz;i++){ans[i]=i;}
  for(int i=1,L=2;i<sz;i<<=1,L<<=1){
    for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
      for(int j=lf;j<mid;j++){lw[j]=mid; hg[j]=rg;}
    }
    for(int dif=i;dif>0;dif>>=1){
      for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
        for(int j=lf;j<mid;j++){
          A[j]=lw[j]+dif/2;
          A[j+i]=j;
        }
      }
      ask();
      for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
        for(int j=lf;j<mid;j++){
          if(C[A[j]]){C[A[j]]--; hg[j]=A[j];}
          else{lw[j]=A[j];}
        }
      }
    }
    for(int lf=0,mid=i,rg=L;lf<sz;lf+=L,mid+=L,rg+=L){
      for(int j=lf,k=mid,idx=lf;idx<rg;){
        while(j<mid && hg[j]<=k){tmp[idx++]=ans[j++];}
        if(k<rg){tmp[idx++]=ans[k++];}
      }
    }
    ans=tmp;
  }
  for(int i=0;i<sz;i++){tmp[ans[i]]=i+1;}
  cout<<"! "<<tmp<<endl;

  
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3628
final_rank: 1

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

using namespace std;

int n;

vector<int> query(vector<int> &a) {
    cout << "?";
    for (int i = 0; i < (1 << n); i++) {
        cout << " " << a[i] + 1;
    }
    cout << endl;
    vector<int> c(1 << n);
    for (int i = 0; i < (1 << n); i++) {
        cin >> c[i];
    }
    return c;
}

void answer(vector<int> &p) {
    cout << "!";
    for (int i = 0; i < (1 << n); i++) {
        cout << " " << p[i] + 1;
    }
    cout << endl;
}

int main() {
    cin >> n;
    int sz = 1 << n;

    vector<vector<int>> v(sz, vector<int>(1));
    for (int i = 0; i < sz; i++) {
        v[i][0] = i;
    }

    for (int z = 0; z < n; z++) {
        vector<int> ref(1 << z, 0);
        int pre = 0;
        for (int b = 0; b < z; b++) {
            for (int i = pre; i < pre + (1 << b); i++) {
                if (b < z - 1) ref[2 * i + 1] = ref[i];
                ref[i] += 1 << (z - 1 - b);
                if (b < z - 1) ref[2 * i + 2] = ref[i];
                ref[i]--;
            }
            pre += (1 << b);
        }
    }

    vector<int> ret;
    for (int z = 0; z < n; z++) {
        vector<int> a(sz);
        int c = (1 << (n - 1 - z));

        for (int k = 0; k < c; k++) {
            vector<int> &s = v[2 * k], &t = v[2 * k + 1];
            for (auto &x : s) a[x] = s[0];
            for (auto &x : t) a[x] = s[0];
            a[t.back()] = s.back();
        }
        ret = query(a);
        for (int k = 0; k < c; k++) {
            if (ret[v[2 * k].back()]) swap(v[2 * k], v[2 * k + 1]);
        }

        vector<int> ref(1 << z, 0);
        int pre = 0;
        for (int b = 0; b < z; b++) {
            for (int i = pre; i < pre + (1 << b); i++) {
                if (b < z - 1) ref[2 * i + 1] = ref[i];
                ref[i] += 1 << (z - 1 - b);
                if (b < z - 1) ref[2 * i + 2] = ref[i];
                ref[i]--;
            }
            pre += (1 << b);
        }

        vector<vector<int>> num(c, vector<int>(1 << (z + 1)));
        for (int k = 0; k < c; k++) num[k][0] = 1 << z;

        pre = 0;
        for (int b = 0; b < z; b++) {
            for (int k = 0; k < c; k++) {
                int sum = 0;
                for (int i = pre; i < pre + (1 << b); i++) {
                    for (int j = 0; j < num[k][i]; j++)
                        a[v[2 * k][j + sum]] = v[2 * k + 1][ref[i]];
                    sum += num[k][i];
                }
                for (auto &x : v[2 * k + 1]) a[x] = v[2 * k][0];
            }
            ret = query(a);
            for (int k = 0; k < c; k++) {
                int sum = 0;
                for (int i = pre; i < pre + (1 << b); i++) {
                    int x = ret[v[2 * k + 1][ref[i]]];
                    num[k][2 * i + 1] = x;
                    num[k][2 * i + 2] = num[k][i] - x;
                }
            }
            pre += (1 << b);
        }

        vector<vector<int>> w(c);
        for (int k = 0; k < c; k++) {
            int sum = 0;
            for (int i = 0; i < (1 << z); i++) {
                for (int j = 0; j < num[k][i + (1 << z) - 1]; j++) {
                    w[k].push_back(v[2 * k][j + sum]);
                }
                sum += num[k][i + (1 << z) - 1];
                w[k].push_back(v[2 * k + 1][i]);
            }
        }

        v = w;
    }

    vector<int> ans(sz);
    for (int i = 0; i < sz; i++) ans[v[0][i]] = i;
    answer(ans);
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3632
final_rank: 3