| #include <iostream> |
| #include <vector> |
| #include <numeric> |
| #include <algorithm> |
| #include <random> |
|
|
| using namespace std; |
|
|
| |
| int n; |
| vector<int> p; |
| vector<int> pos_of_val; |
|
|
| |
| int query(const vector<int>& q) { |
| cout << "0"; |
| for (int x : q) { |
| cout << " " << x; |
| } |
| cout << endl; |
| int res; |
| cin >> res; |
| return res; |
| } |
|
|
| |
| void answer(const vector<int>& ans) { |
| cout << "1"; |
| for (int x : ans) { |
| cout << " " << x; |
| } |
| cout << endl; |
| exit(0); |
| } |
|
|
| int main() { |
| |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
|
|
| if (!(cin >> n)) return 0; |
|
|
| p.assign(n, 0); |
| pos_of_val.assign(n + 1, -1); |
| |
| |
| vector<int> u(n); |
| iota(u.begin(), u.end(), 0); |
|
|
| |
| if (n == 1) { |
| answer({1}); |
| } |
|
|
| |
| mt19937 rng(1337); |
|
|
| |
| |
| |
| |
| vector<int> candidates = u; |
| |
| while (candidates.size() > 1) { |
| int sz = candidates.size(); |
| int mid = sz / 2; |
| vector<int> L, R; |
| L.reserve(mid); |
| R.reserve(sz - mid); |
| for(int i=0; i<mid; ++i) L.push_back(candidates[i]); |
| for(int i=mid; i<sz; ++i) R.push_back(candidates[i]); |
|
|
| bool found_split = false; |
| while (!found_split) { |
| |
| int f = 2 + (rng() % (n - 1)); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| vector<int> q(n, 1); |
| for(int idx : R) q[idx] = f; |
| |
| int s = query(q); |
| if (s == 2) { |
| candidates = L; |
| found_split = true; |
| } else if (s == 0) { |
| candidates = R; |
| found_split = true; |
| } |
| } |
| } |
| |
| int pos1 = candidates[0]; |
| p[pos1] = 1; |
| pos_of_val[1] = pos1; |
| |
| |
| vector<int> next_u; |
| next_u.reserve(n-1); |
| for(int idx : u) { |
| if(idx != pos1) next_u.push_back(idx); |
| } |
| u = next_u; |
| |
| |
| |
| |
| |
| for (int k = 2; k < n; ++k) { |
| vector<int> cur_candidates = u; |
| while (cur_candidates.size() > 1) { |
| int sz = cur_candidates.size(); |
| int mid = sz / 2; |
| vector<int> L, R; |
| L.reserve(mid); |
| for(int i=0; i<mid; ++i) L.push_back(cur_candidates[i]); |
| for(int i=mid; i<sz; ++i) R.push_back(cur_candidates[i]); |
| |
| |
| |
| |
| |
| |
| |
| vector<int> q(n, 1); |
| for (int v = 1; v < k; ++v) { |
| q[pos_of_val[v]] = v; |
| } |
| for (int idx : L) { |
| q[idx] = k; |
| } |
| |
| |
| |
| |
| |
| |
| int s = query(q); |
| if (s == k) { |
| cur_candidates = L; |
| } else { |
| cur_candidates = R; |
| } |
| } |
| |
| int posk = cur_candidates[0]; |
| p[posk] = k; |
| pos_of_val[k] = posk; |
| |
| |
| vector<int> nu; |
| nu.reserve(u.size()-1); |
| for(int idx : u) { |
| if(idx != posk) nu.push_back(idx); |
| } |
| u = nu; |
| } |
| |
| |
| if (!u.empty()) { |
| p[u[0]] = n; |
| } |
| |
| answer(p); |
| |
| return 0; |
| } |