| #include <iostream> |
| #include <vector> |
| #include <numeric> |
| #include <cmath> |
| #include <cstdlib> |
| #include <ctime> |
| #include <algorithm> |
|
|
| using namespace std; |
|
|
| |
| int query(const vector<int>& q) { |
| cout << "0"; |
| for (int x : q) { |
| cout << " " << x; |
| } |
| cout << endl; |
| int res; |
| cin >> res; |
| return res; |
| } |
|
|
| |
| void guess(const vector<int>& p) { |
| cout << "1"; |
| for (int x : p) { |
| cout << " " << x; |
| } |
| cout << endl; |
| exit(0); |
| } |
|
|
| int main() { |
| |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
| srand(time(NULL)); |
|
|
| int n; |
| if (!(cin >> n)) return 0; |
|
|
| |
| vector<int> p_ans(n + 1, 0); |
| vector<int> unknown(n); |
| iota(unknown.begin(), unknown.end(), 1); |
|
|
| |
| |
| |
| { |
| vector<int> current_u = unknown; |
| while (current_u.size() > 1) { |
| int sz = current_u.size(); |
| int mid = sz / 2; |
| vector<int> L, R; |
| for (int i = 0; i < mid; ++i) L.push_back(current_u[i]); |
| for (int i = mid; i < sz; ++i) R.push_back(current_u[i]); |
|
|
| |
| vector<bool> in_L(n + 1, false); |
| for (int x : L) in_L[x] = true; |
|
|
| bool found_in_L = false; |
| bool determined = false; |
| |
| |
| |
| |
| |
| double p = (double)L.size() / n; |
| int limit = 30; |
| if (p < 0.5) { |
| if (p > 1e-9) { |
| double val = -20.7 / log(p); |
| limit = (int)ceil(val); |
| if (limit < 2) limit = 2; |
| if (limit > 35) limit = 35; |
| } else { |
| limit = 2; |
| } |
| } |
|
|
| int tries = 0; |
| while (tries < limit) { |
| tries++; |
| |
| int v = 2 + rand() % (n - 1); |
| |
| vector<int> q(n); |
| for (int i = 1; i <= n; ++i) { |
| if (in_L[i]) q[i-1] = 1; |
| else q[i-1] = v; |
| } |
| |
| int score = query(q); |
| |
| |
| |
| if (score == 2) { |
| found_in_L = true; |
| determined = true; |
| break; |
| } else if (score == 0) { |
| found_in_L = false; |
| determined = true; |
| break; |
| } |
| } |
| |
| if (!determined) { |
| |
| |
| |
| |
| found_in_L = false; |
| } |
|
|
| if (found_in_L) current_u = L; |
| else current_u = R; |
| } |
| p_ans[current_u[0]] = 1; |
| } |
|
|
| |
| |
| |
| vector<bool> position_filled(n + 1, false); |
| for(int i=1; i<=n; ++i) if(p_ans[i] != 0) position_filled[i] = true; |
|
|
| for (int k = 2; k <= n; ++k) { |
| vector<int> available; |
| for (int i = 1; i <= n; ++i) { |
| if (!position_filled[i]) available.push_back(i); |
| } |
|
|
| if (available.empty()) break; |
| |
| |
| int low = 0, high = available.size() - 1; |
| while (low < high) { |
| int mid = low + (high - low) / 2; |
| |
| vector<int> q(n); |
| |
| |
| |
| |
| for (int i = 1; i <= n; ++i) { |
| if (position_filled[i]) { |
| q[i-1] = p_ans[i]; |
| } else { |
| q[i-1] = 1; |
| } |
| } |
| |
| for (int i = low; i <= mid; ++i) { |
| q[available[i]-1] = k; |
| } |
|
|
| int score = query(q); |
| |
| |
| |
| |
| if (score == k) { |
| high = mid; |
| } else { |
| low = mid + 1; |
| } |
| } |
| p_ans[available[low]] = k; |
| position_filled[available[low]] = true; |
| } |
|
|
| |
| vector<int> res; |
| for (int i = 1; i <= n; ++i) res.push_back(p_ans[i]); |
| guess(res); |
|
|
| return 0; |
| } |