| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| static int SUBTASK, N; |
|
|
| static vector<int> ask(const vector<int>& ops) { |
| cout << ops.size(); |
| for (int x : ops) cout << ' ' << x; |
| cout << '\n'; |
| cout.flush(); |
|
|
| vector<int> res(ops.size()); |
| for (size_t i = 0; i < ops.size(); i++) { |
| if (!(cin >> res[i])) exit(0); |
| if (res[i] == -1) exit(0); |
| } |
| return res; |
| } |
|
|
| static void clear_set(const vector<int>& on) { |
| if (on.empty()) return; |
| (void)ask(on); |
| } |
|
|
| |
| static vector<int> build_maximal_independent(const vector<int>& order, vector<char>& inSet) { |
| vector<int> picked; |
| picked.reserve(order.size()); |
| for (int v : order) { |
| auto res = ask(vector<int>{v}); |
| if (res[0] == 0) { |
| inSet[v] = 1; |
| picked.push_back(v); |
| } else { |
| (void)ask(vector<int>{v}); |
| } |
| } |
| return picked; |
| } |
|
|
| |
| |
| static void find_neighbors_up_to2(const vector<int>& anchors, |
| const vector<int>& vertices, |
| vector<vector<int>>& neighOut) { |
| int m = (int)anchors.size(); |
| if (vertices.empty()) return; |
| if (m == 0) return; |
| if (m == 1) { |
| int a = anchors[0]; |
| for (int v : vertices) neighOut[v].push_back(a); |
| return; |
| } |
|
|
| struct Node { |
| int l, r; |
| vector<int> vs; |
| int mid = 0; |
| int leftIdx = -1, rightIdx = -1; |
| bool split = false; |
| }; |
|
|
| vector<Node> cur; |
| cur.push_back(Node{0, m, vertices}); |
|
|
| while (true) { |
| bool anySplit = false; |
|
|
| vector<Node> next; |
| next.reserve(cur.size() * 2); |
|
|
| |
| for (auto &nd : cur) { |
| nd.split = false; |
| nd.leftIdx = nd.rightIdx = -1; |
| if (nd.r - nd.l <= 1) { |
| nd.split = false; |
| nd.leftIdx = (int)next.size(); |
| next.push_back(Node{nd.l, nd.r, nd.vs}); |
| } else { |
| anySplit = true; |
| nd.split = true; |
| nd.mid = (nd.l + nd.r) >> 1; |
| nd.leftIdx = (int)next.size(); |
| next.push_back(Node{nd.l, nd.mid, {}}); |
| nd.rightIdx = (int)next.size(); |
| next.push_back(Node{nd.mid, nd.r, {}}); |
| } |
| } |
|
|
| if (!anySplit) { |
| |
| for (const auto &nd : cur) { |
| |
| int a = anchors[nd.l]; |
| for (int v : nd.vs) neighOut[v].push_back(a); |
| } |
| return; |
| } |
|
|
| |
| vector<int> ops; |
| |
| ops.reserve((size_t)4 * (size_t)m + (size_t)8 * (size_t)vertices.size() + 100); |
|
|
| for (const auto &nd : cur) { |
| if (!nd.split) continue; |
| int l = nd.l, mid = nd.mid, r = nd.r; |
|
|
| |
| for (int i = l; i < mid; i++) ops.push_back(anchors[i]); |
| for (int v : nd.vs) { |
| ops.push_back(v); |
| ops.push_back(v); |
| } |
| for (int i = l; i < mid; i++) ops.push_back(anchors[i]); |
|
|
| |
| for (int i = mid; i < r; i++) ops.push_back(anchors[i]); |
| for (int v : nd.vs) { |
| ops.push_back(v); |
| ops.push_back(v); |
| } |
| for (int i = mid; i < r; i++) ops.push_back(anchors[i]); |
| } |
|
|
| auto res = ask(ops); |
| size_t pos = 0; |
|
|
| |
| for (const auto &nd : cur) { |
| if (!nd.split) continue; |
| int l = nd.l, mid = nd.mid, r = nd.r; |
|
|
| |
| pos += (size_t)(mid - l); |
| |
| for (int v : nd.vs) { |
| int bit = res[pos]; |
| pos += 2; |
| if (bit) next[nd.leftIdx].vs.push_back(v); |
| } |
| |
| pos += (size_t)(mid - l); |
|
|
| |
| pos += (size_t)(r - mid); |
| for (int v : nd.vs) { |
| int bit = res[pos]; |
| pos += 2; |
| if (bit) next[nd.rightIdx].vs.push_back(v); |
| } |
| pos += (size_t)(r - mid); |
| } |
|
|
| cur.swap(next); |
| |
| } |
| } |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
|
|
| if (!(cin >> SUBTASK >> N)) return 0; |
|
|
| if (N == 1) { |
| cout << -1 << " 1\n"; |
| cout.flush(); |
| return 0; |
| } |
| if (N == 2) { |
| |
| cout << -1 << " 1 2\n"; |
| cout.flush(); |
| return 0; |
| } |
|
|
| |
| vector<int> order(N); |
| iota(order.begin(), order.end(), 1); |
| |
| { |
| uint64_t seed = 1469598103934665603ULL; |
| seed ^= (uint64_t)N + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2); |
| seed ^= (uint64_t)SUBTASK + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2); |
| mt19937 rng((uint32_t)(seed ^ (seed >> 32))); |
| shuffle(order.begin(), order.end(), rng); |
| } |
|
|
| vector<char> inI(N + 1, 0); |
| vector<int> I = build_maximal_independent(order, inI); |
| clear_set(I); |
|
|
| |
| vector<int> R; |
| R.reserve(N - (int)I.size()); |
| for (int v = 1; v <= N; v++) if (!inI[v]) R.push_back(v); |
|
|
| |
| vector<vector<int>> neighI(N + 1); |
| find_neighbors_up_to2(I, R, neighI); |
|
|
| |
| vector<int> R1; |
| R1.reserve(R.size()); |
| for (int v : R) { |
| if ((int)neighI[v].size() == 1) R1.push_back(v); |
| |
| } |
|
|
| |
| vector<vector<int>> adj(N + 1); |
| adj.reserve(N + 1); |
|
|
| auto add_edge = [&](int a, int b) { |
| adj[a].push_back(b); |
| adj[b].push_back(a); |
| }; |
|
|
| for (int v : R) { |
| for (int u : neighI[v]) add_edge(v, u); |
| } |
|
|
| |
| if (!R1.empty()) { |
| |
| vector<char> inJ(N + 1, 0); |
| vector<int> J = build_maximal_independent(R1, inJ); |
| clear_set(J); |
|
|
| vector<int> W; |
| W.reserve(R1.size() - J.size()); |
| for (int v : R1) if (!inJ[v]) W.push_back(v); |
|
|
| |
| vector<vector<int>> neighJ(N + 1); |
| find_neighbors_up_to2(J, W, neighJ); |
|
|
| for (int w : W) { |
| if (neighJ[w].empty()) exit(0); |
| int partner = neighJ[w][0]; |
| add_edge(w, partner); |
| } |
| } |
|
|
| |
| |
| int start = 1; |
| while (start <= N && adj[start].empty()) start++; |
| if (start > N) exit(0); |
|
|
| vector<int> perm; |
| perm.reserve(N); |
|
|
| int prev = 0, cur = start; |
| for (int i = 0; i < N; i++) { |
| perm.push_back(cur); |
| if ((int)adj[cur].size() == 0) exit(0); |
| int nxt; |
| if ((int)adj[cur].size() == 1) { |
| nxt = adj[cur][0]; |
| } else { |
| int a = adj[cur][0], b = adj[cur][1]; |
| nxt = (a == prev ? b : a); |
| } |
| prev = cur; |
| cur = nxt; |
| } |
|
|
| cout << -1; |
| for (int x : perm) cout << ' ' << x; |
| cout << '\n'; |
| cout.flush(); |
| return 0; |
| } |