#include using namespace std; static int SUBTASK, N; static vector ask(const vector& ops) { cout << ops.size(); for (int x : ops) cout << ' ' << x; cout << '\n'; cout.flush(); vector 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& on) { if (on.empty()) return; (void)ask(on); } // Greedy maximal independent set on given vertex order; leaves the set lit at the end. static vector build_maximal_independent(const vector& order, vector& inSet) { vector picked; picked.reserve(order.size()); for (int v : order) { auto res = ask(vector{v}); if (res[0] == 0) { inSet[v] = 1; picked.push_back(v); } else { (void)ask(vector{v}); // revert } } return picked; } // Given independent anchors A and vertices V, find for each v in V all neighbors in A (up to 2). // Assumes S is empty on entry, and leaves S empty on exit. static void find_neighbors_up_to2(const vector& anchors, const vector& vertices, vector>& 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 vs; int mid = 0; int leftIdx = -1, rightIdx = -1; bool split = false; }; vector cur; cur.push_back(Node{0, m, vertices}); while (true) { bool anySplit = false; vector next; next.reserve(cur.size() * 2); // Prepare next nodes and record child indices. 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) { // All leaves. Collect results. for (const auto &nd : cur) { // nd.l == nd.r-1 int a = anchors[nd.l]; for (int v : nd.vs) neighOut[v].push_back(a); } return; } // Build one big query for this level: for each split node, test left and right halves. vector ops; // Conservative reserve: anchors toggles (4m) + vertex toggles (~8*|V|) 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; // Left half test for (int i = l; i < mid; i++) ops.push_back(anchors[i]); // on for (int v : nd.vs) { ops.push_back(v); // on ops.push_back(v); // off } for (int i = l; i < mid; i++) ops.push_back(anchors[i]); // off // Right half test for (int i = mid; i < r; i++) ops.push_back(anchors[i]); // on for (int v : nd.vs) { ops.push_back(v); // on ops.push_back(v); // off } for (int i = mid; i < r; i++) ops.push_back(anchors[i]); // off } auto res = ask(ops); size_t pos = 0; // Parse and distribute vertices into next. for (const auto &nd : cur) { if (!nd.split) continue; int l = nd.l, mid = nd.mid, r = nd.r; // Left half: skip anchor on outputs pos += (size_t)(mid - l); // For each v: read bit on first toggle, skip second toggle for (int v : nd.vs) { int bit = res[pos]; pos += 2; if (bit) next[nd.leftIdx].vs.push_back(v); } // skip anchor off outputs pos += (size_t)(mid - l); // Right half 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); // S should be empty after the batch; our construction toggles everything off. } } 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) { // Any order is fine cout << -1 << " 1 2\n"; cout.flush(); return 0; } // Build maximal independent set I vector order(N); iota(order.begin(), order.end(), 1); // Optional shuffle for better typical size; deterministic seed. { 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 inI(N + 1, 0); vector I = build_maximal_independent(order, inI); clear_set(I); // ensure S is empty // Outside vertices vector R; R.reserve(N - (int)I.size()); for (int v = 1; v <= N; v++) if (!inI[v]) R.push_back(v); // Find for each outside vertex its neighbors in I (size 1 or 2) vector> neighI(N + 1); find_neighbors_up_to2(I, R, neighI); // Separate R1 (one anchor neighbor) and R2 (two anchor neighbors) vector R1; R1.reserve(R.size()); for (int v : R) { if ((int)neighI[v].size() == 1) R1.push_back(v); // size==2 -> singleton, no outside neighbor } // Build edges vector> 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 there are R1 vertices, find their matching (outside-outside edges) if (!R1.empty()) { // Build maximal independent set J in matching graph induced by R1 vector inJ(N + 1, 0); vector J = build_maximal_independent(R1, inJ); clear_set(J); // empty vector W; W.reserve(R1.size() - J.size()); for (int v : R1) if (!inJ[v]) W.push_back(v); // Find each w's unique neighbor in J vector> 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); } } // Build a cycle traversal order // Ensure degrees are usable; for robustness, pick a start with nonempty adjacency. int start = 1; while (start <= N && adj[start].empty()) start++; if (start > N) exit(0); vector 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; }