| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| |
| static uint64_t splitmix64_x; |
| static inline uint64_t splitmix64() { |
| uint64_t z = (splitmix64_x += 0x9e3779b97f4a7c15ULL); |
| z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL; |
| z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL; |
| return z ^ (z >> 31); |
| } |
|
|
| struct Interactor { |
| |
| static vector<int> query(const vector<int>& ops) { |
| int L = (int)ops.size(); |
| cout << L; |
| for (int x : ops) { |
| cout << " " << x; |
| } |
| cout << endl; |
| cout.flush(); |
| vector<int> res(L); |
| for (int i = 0; i < L; ++i) { |
| if (!(cin >> res[i])) { |
| |
| res[i] = 0; |
| } |
| } |
| return res; |
| } |
| }; |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
|
|
| int subtask; |
| int n; |
| if (!(cin >> subtask >> n)) { |
| return 0; |
| } |
|
|
| splitmix64_x = 0x123456789abcdef1ULL ^ (uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count(); |
|
|
| |
| vector<char> isS(n + 1, 0); |
| vector<char> isOn(n + 1, 0); |
| vector<int> Slist; |
| Slist.reserve(n); |
| for (int id = 1; id <= n; ++id) { |
| |
| { |
| vector<int> ops = {id}; |
| vector<int> res = Interactor::query(ops); |
| int r = res[0]; |
| if (r == 0) { |
| |
| isS[id] = 1; |
| isOn[id] = 1; |
| Slist.push_back(id); |
| } else { |
| |
| ops = {id}; |
| res = Interactor::query(ops); |
| isOn[id] = 0; |
| } |
| } |
| } |
| int M = (int)Slist.size(); |
| vector<int> Ulist; |
| Ulist.reserve(n - M); |
| for (int id = 1; id <= n; ++id) if (!isS[id]) Ulist.push_back(id); |
|
|
| |
| if (M == 0) { |
| cout << -1; |
| for (int i = 1; i <= n; ++i) cout << " " << i; |
| cout << endl; |
| cout.flush(); |
| return 0; |
| } |
|
|
| |
| const int K = 64; |
|
|
| vector<int> sIndexOfLabel(n + 1, -1); |
| for (int i = 0; i < M; ++i) sIndexOfLabel[Slist[i]] = i; |
|
|
| vector<uint64_t> codeS(M); |
| unordered_map<uint64_t, int> code2SLabel; |
| code2SLabel.reserve(M * 2); |
| code2SLabel.max_load_factor(0.7f); |
| for (int i = 0; i < M; ++i) { |
| |
| uint64_t c; |
| do { |
| c = splitmix64(); |
| } while (code2SLabel.find(c) != code2SLabel.end()); |
| codeS[i] = c; |
| code2SLabel[c] = Slist[i]; |
| } |
|
|
| |
| int WC = (M + 63) >> 6; |
| vector< vector<uint64_t> > BitsZero(K, vector<uint64_t>(WC, 0)); |
| for (int j = 0; j < K; ++j) { |
| for (int i = 0; i < M; ++i) { |
| if (((codeS[i] >> j) & 1ULL) == 0ULL) { |
| BitsZero[j][i >> 6] |= (1ULL << (i & 63)); |
| } |
| } |
| } |
| |
| uint64_t lastMask = (M % 64 == 0) ? ~0ULL : ((1ULL << (M % 64)) - 1ULL); |
|
|
| |
| vector<uint64_t> rbits(n + 1, 0); |
|
|
| |
| vector< vector<int> > Rj_list(K); |
| for (int j = 0; j < K; ++j) { |
| vector<int>& R = Rj_list[j]; |
| R.reserve(M / 2 + 1); |
| for (int i = 0; i < M; ++i) { |
| if (((codeS[i] >> j) & 1ULL) == 0ULL) { |
| R.push_back(Slist[i]); |
| } |
| } |
| } |
|
|
| for (int j = 0; j < K; ++j) { |
| const vector<int>& R = Rj_list[j]; |
| vector<int> ops; |
| ops.reserve(R.size() + Ulist.size() * 2 + R.size()); |
| |
| for (int x : R) ops.push_back(x); |
| |
| for (int u : Ulist) { |
| ops.push_back(u); |
| ops.push_back(u); |
| } |
| |
| for (int x : R) ops.push_back(x); |
|
|
| vector<int> res = Interactor::query(ops); |
| int pos = 0; |
| pos += (int)R.size(); |
| for (int idx = 0; idx < (int)Ulist.size(); ++idx) { |
| int u = Ulist[idx]; |
| int bit = res[pos++]; |
| |
| pos++; |
| if (bit) rbits[u] |= (1ULL << j); |
| } |
| |
| |
| |
| } |
|
|
| |
| |
| vector< array<int, 2> > adj(n + 1, array<int, 2>{-1, -1}); |
| vector<int> deg(n + 1, 0); |
|
|
| auto add_edge = [&](int a, int b) { |
| if (deg[a] < 2) adj[a][deg[a]++] = b; |
| if (deg[b] < 2) adj[b][deg[b]++] = a; |
| }; |
|
|
| |
| vector< vector<int> > UneighborsOfS(n + 1); |
| UneighborsOfS.assign(n + 1, {}); |
|
|
| |
| vector<char> isDeg1U(n + 1, 0); |
| vector<char> isDeg2U(n + 1, 0); |
| vector< array<int, 2> > N_S_of_U(n + 1); |
| for (int u : Ulist) { |
| auto it = code2SLabel.find(rbits[u]); |
| if (it != code2SLabel.end()) { |
| int s = it->second; |
| isDeg1U[u] = 1; |
| N_S_of_U[u][0] = s; |
| N_S_of_U[u][1] = -1; |
| add_edge(u, s); |
| UneighborsOfS[s].push_back(u); |
| } |
| } |
|
|
| |
| |
| vector<uint64_t> cand(WC); |
| for (int u : Ulist) { |
| if (isDeg1U[u]) continue; |
| uint64_t r = rbits[u]; |
| |
| |
| for (int w = 0; w < WC; ++w) cand[w] = ~0ULL; |
| |
| cand[WC - 1] &= lastMask; |
| for (int j = 0; j < K; ++j) { |
| if (((r >> j) & 1ULL) == 0ULL) { |
| |
| const vector<uint64_t>& bz = BitsZero[j]; |
| for (int w = 0; w < WC; ++w) cand[w] &= bz[w]; |
| } |
| } |
| |
| vector<int> candidates; |
| for (int w = 0; w < WC; ++w) { |
| uint64_t x = cand[w]; |
| while (x) { |
| int b = __builtin_ctzll(x); |
| int idxS = (w << 6) + b; |
| if (idxS < M) candidates.push_back(idxS); |
| x &= x - 1ULL; |
| } |
| } |
| |
| int s1 = -1, s2 = -1; |
| if (candidates.size() == 1) { |
| |
| |
| int idx = candidates[0]; |
| uint64_t c1 = codeS[idx]; |
| |
| bool found = false; |
| for (int j = 0; j < M; ++j) { |
| if (j == idx) continue; |
| if ( (c1 | codeS[j]) == r ) { |
| s1 = Slist[idx]; |
| s2 = Slist[j]; |
| found = true; |
| break; |
| } |
| } |
| if (!found) { |
| |
| s1 = Slist[idx]; |
| s2 = -1; |
| } |
| } else { |
| bool found = false; |
| for (size_t a = 0; a < candidates.size() && !found; ++a) { |
| uint64_t c1 = codeS[candidates[a]]; |
| for (size_t b = a + 1; b < candidates.size(); ++b) { |
| uint64_t c2 = codeS[candidates[b]]; |
| if ((c1 | c2) == r) { |
| s1 = Slist[candidates[a]]; |
| s2 = Slist[candidates[b]]; |
| found = true; |
| break; |
| } |
| } |
| } |
| if (!found) { |
| |
| |
| bool ok = false; |
| for (int idxA : candidates) { |
| uint64_t c1 = codeS[idxA]; |
| for (int j = 0; j < M; ++j) { |
| if (j == idxA) continue; |
| if ((c1 | codeS[j]) == r) { |
| s1 = Slist[idxA]; |
| s2 = Slist[j]; |
| ok = true; |
| break; |
| } |
| } |
| if (ok) break; |
| } |
| if (!ok) { |
| |
| if (candidates.size() >= 2) { |
| s1 = Slist[candidates[0]]; |
| s2 = Slist[candidates[1]]; |
| } else { |
| |
| s1 = -1; |
| s2 = -1; |
| } |
| } |
| } |
| } |
| if (s1 != -1) { |
| if (s2 != -1) { |
| isDeg2U[u] = 1; |
| N_S_of_U[u][0] = s1; |
| N_S_of_U[u][1] = s2; |
| add_edge(u, s1); |
| add_edge(u, s2); |
| UneighborsOfS[s1].push_back(u); |
| UneighborsOfS[s2].push_back(u); |
| } else { |
| |
| isDeg1U[u] = 1; |
| N_S_of_U[u][0] = s1; |
| N_S_of_U[u][1] = -1; |
| add_edge(u, s1); |
| UneighborsOfS[s1].push_back(u); |
| } |
| } else { |
| |
| } |
| } |
|
|
| |
| |
| vector<int> Udeg1; |
| for (int u : Ulist) if (isDeg1U[u]) Udeg1.push_back(u); |
|
|
| |
| { |
| vector<int> ops; |
| ops.reserve(Slist.size()); |
| for (int s : Slist) { |
| if (isOn[s]) { |
| ops.push_back(s); |
| isOn[s] = 0; |
| } |
| } |
| if (!ops.empty()) { |
| (void)Interactor::query(ops); |
| } |
| } |
|
|
| |
| vector<char> inT(n + 1, 0); |
| vector<int> Tlist; |
| Tlist.reserve(Udeg1.size() / 2 + 1); |
| for (int u : Udeg1) { |
| |
| vector<int> res1 = Interactor::query(vector<int>{u}); |
| int r = res1[0]; |
| if (r == 0) { |
| |
| inT[u] = 1; |
| Tlist.push_back(u); |
| isOn[u] = 1; |
| } else { |
| |
| vector<int> res2 = Interactor::query(vector<int>{u}); |
| isOn[u] = 0; |
| (void)res2; |
| } |
| } |
|
|
| |
| |
| int Tcnt = (int)Tlist.size(); |
| if (Tcnt > 0) { |
| int KT = 0; |
| while ((1 << KT) < Tcnt) ++KT; |
| KT = max(KT, 1); |
| |
| vector<uint64_t> codeT(n + 1, 0); |
| unordered_map<uint64_t, int> code2T; code2T.reserve(Tcnt*2); code2T.max_load_factor(0.7f); |
| for (int i = 0; i < Tcnt; ++i) { |
| uint64_t c = splitmix64(); |
| |
| |
| |
| c = (uint64_t)i; |
| codeT[Tlist[i]] = c; |
| code2T[c] = Tlist[i]; |
| } |
|
|
| vector<uint64_t> rT(n + 1, 0); |
| |
| for (int j = 0; j < KT; ++j) { |
| vector<int> R; R.reserve(Tcnt/2+1); |
| for (int u : Tlist) { |
| if (((codeT[u] >> j) & 1ULL) == 0ULL) R.push_back(u); |
| } |
| vector<int> ops; |
| ops.reserve(R.size() + Udeg1.size() * 2 + R.size()); |
| |
| for (int x : R) { ops.push_back(x); isOn[x] = 0; } |
| |
| for (int v : Udeg1) if (!inT[v]) { ops.push_back(v); ops.push_back(v); } |
| |
| for (int x : R) { ops.push_back(x); isOn[x] = 1; } |
| vector<int> res = Interactor::query(ops); |
| int pos = 0; |
| pos += (int)R.size(); |
| for (int v : Udeg1) if (!inT[v]) { |
| int bit = res[pos++]; |
| pos++; |
| if (bit) rT[v] |= (1ULL << j); |
| } |
| |
| } |
|
|
| |
| for (int v : Udeg1) if (!inT[v]) { |
| uint64_t code = rT[v]; |
| auto it = code2T.find(code); |
| if (it != code2T.end()) { |
| int u = it->second; |
| |
| add_edge(u, v); |
| } else { |
| |
| |
| uint64_t idx = code & ((1ULL << KT) - 1ULL); |
| int u = Tlist[(int)(idx % Tcnt)]; |
| add_edge(u, v); |
| } |
| } |
|
|
| |
| vector<int> ops_off; |
| ops_off.reserve(Tcnt); |
| for (int u : Tlist) if (isOn[u]) ops_off.push_back(u), isOn[u] = 0; |
| if (!ops_off.empty()) { |
| (void)Interactor::query(ops_off); |
| } |
| } |
|
|
| |
| |
| |
| |
|
|
| |
|
|
| |
| vector<int> ring; |
| ring.reserve(n); |
| int start = 1; |
| |
| if (deg[start] != 2) { |
| for (int i = 1; i <= n; ++i) if (deg[i] == 2) { start = i; break; } |
| } |
| int prev = -1, cur = start; |
| ring.push_back(cur); |
| for (int step = 1; step < n; ++step) { |
| int nxt = -1; |
| if (deg[cur] >= 1) { |
| int a = adj[cur][0]; |
| int b = (deg[cur] >= 2 ? adj[cur][1] : -1); |
| if (a != -1 && a != prev) nxt = a; |
| else if (b != -1 && b != prev) nxt = b; |
| } |
| if (nxt == -1) { |
| |
| |
| for (int i = 1; i <= n; ++i) { |
| bool used = false; |
| for (int x : ring) if (x == i) { used = true; break; } |
| if (!used) { nxt = i; break; } |
| } |
| } |
| prev = cur; |
| cur = nxt; |
| ring.push_back(cur); |
| } |
|
|
| |
| cout << -1; |
| for (int x : ring) cout << " " << x; |
| cout << endl; |
| cout.flush(); |
| return 0; |
| } |