File size: 3,444 Bytes
14c9c2b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #include <bits/stdc++.h>
using namespace std;
static int n;
static vector<int> qv;
static int ask(const vector<int>& q) {
cout << 0;
for (int i = 1; i <= n; i++) cout << ' ' << q[i];
cout << '\n';
cout.flush();
int x;
if (!(cin >> x)) exit(0);
if (x == -1) exit(0);
return x;
}
static int find_pos1() {
if (n == 1) return 1;
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
vector<int> cand;
auto try_subset = [&](const vector<int>& subset, const vector<int>& complement) -> bool {
fill(qv.begin() + 1, qv.end(), 1);
for (int p : subset) qv[p] = 2;
int ans = ask(qv);
if (ans == 0) { cand = subset; return true; } // pos1 in subset
if (ans == 2) { cand = complement; return true; } // pos1 in complement
return false;
};
// Random half splits
vector<int> pos(n);
iota(pos.begin(), pos.end(), 1);
int h = n / 2;
for (int it = 0; it < 30 && cand.empty(); it++) {
shuffle(pos.begin(), pos.end(), rng);
vector<int> subset(pos.begin(), pos.begin() + h);
vector<int> comp(pos.begin() + h, pos.end());
if (try_subset(subset, comp)) break;
}
// Deterministic bit splits fallback
if (cand.empty()) {
int maxb = 0;
while ((1 << maxb) <= n) maxb++;
for (int b = 0; b <= maxb + 1 && cand.empty(); b++) {
vector<int> subset, comp;
subset.reserve(n);
comp.reserve(n);
for (int i = 1; i <= n; i++) {
if ((i >> b) & 1) subset.push_back(i);
else comp.push_back(i);
}
if (subset.empty() || comp.empty()) continue;
if (try_subset(subset, comp)) break;
}
}
if (cand.empty()) {
// Should never happen, but avoid crash
cand.resize(n);
iota(cand.begin(), cand.end(), 1);
}
// Binary search within cand using answers 0/1
int l = 0, r = (int)cand.size();
while (r - l > 1) {
int mid = (l + r) / 2;
fill(qv.begin() + 1, qv.end(), 1);
for (int i = l; i < mid; i++) qv[cand[i]] = 2;
int ans = ask(qv);
if (ans == 0) r = mid;
else l = mid;
}
return cand[l];
}
static int find_pos_for_value(int val, vector<int>& rem) {
int l = 0, r = (int)rem.size();
while (r - l > 1) {
int mid = (l + r) / 2;
fill(qv.begin() + 1, qv.end(), 1);
for (int i = l; i < mid; i++) qv[rem[i]] = val;
int ans = ask(qv);
if (ans == 2) r = mid;
else l = mid;
}
int pos = rem[l];
rem.erase(rem.begin() + l);
return pos;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
if (!(cin >> n)) return 0;
qv.assign(n + 1, 1);
vector<int> perm(n + 1, 0);
if (n == 1) {
cout << 1 << ' ' << 1 << '\n';
cout.flush();
return 0;
}
int pos1 = find_pos1();
perm[pos1] = 1;
vector<int> rem;
rem.reserve(n - 1);
for (int i = 1; i <= n; i++) if (i != pos1) rem.push_back(i);
for (int v = 2; v <= n - 1; v++) {
int pv = find_pos_for_value(v, rem);
perm[pv] = v;
}
// Remaining position has value n
if (!rem.empty()) perm[rem[0]] = n;
cout << 1;
for (int i = 1; i <= n; i++) cout << ' ' << perm[i];
cout << '\n';
cout.flush();
return 0;
} |