File size: 16,290 Bytes
1fd0050
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
#include <bits/stdc++.h>
using namespace std;

// Random generator: splitmix64
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 {
    // Send a sequence of operations and receive responses
    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])) {
                // In case of EOF or error, fill with zeros to avoid UB; interactive judge won't do this.
                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();

    // Step A: Build a maximal independent set S using greedy toggles
    vector<char> isS(n + 1, 0);
    vector<char> isOn(n + 1, 0); // current interactor state
    vector<int> Slist;
    Slist.reserve(n);
    for (int id = 1; id <= n; ++id) {
        // Toggle id
        {
            vector<int> ops = {id};
            vector<int> res = Interactor::query(ops);
            int r = res[0];
            if (r == 0) {
                // keep id in S
                isS[id] = 1;
                isOn[id] = 1;
                Slist.push_back(id);
            } else {
                // revert
                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);

    // Edge case: if M == 0 (shouldn't happen as S is maximal unless n==0), fallback to output 1..n
    if (M == 0) {
        cout << -1;
        for (int i = 1; i <= n; ++i) cout << " " << i;
        cout << endl;
        cout.flush();
        return 0;
    }

    // Step B: Assign 64-bit random codes to S nodes and perform 64 rounds to compute rbits for U
    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; // maps code to label (id)
    code2SLabel.reserve(M * 2);
    code2SLabel.max_load_factor(0.7f);
    for (int i = 0; i < M; ++i) {
        // Ensure uniqueness (unlikely collision)
        uint64_t c;
        do {
            c = splitmix64();
        } while (code2SLabel.find(c) != code2SLabel.end());
        codeS[i] = c;
        code2SLabel[c] = Slist[i];
    }

    // Precompute BitsZero[j] bitset for S indices: 1 where code bit j == 0
    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));
            }
        }
    }
    // Mask for the last word
    uint64_t lastMask = (M % 64 == 0) ? ~0ULL : ((1ULL << (M % 64)) - 1ULL);

    // For each U node, compute rbits via K rounds
    vector<uint64_t> rbits(n + 1, 0);

    // Pre-construct arrays of R_j lists for S nodes to optimize operations composition
    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());
        // Toggle off R
        for (int x : R) ops.push_back(x);
        // For each U: toggle u on/off
        for (int u : Ulist) {
            ops.push_back(u);
            ops.push_back(u);
        }
        // Restore R
        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++];
            // off toggle result ignored
            pos++;
            if (bit) rbits[u] |= (1ULL << j);
        }
        // skip restores
        // (int)R.size() responses remain to be skipped
        // But we don't need res further
    }

    // Now decode neighbors
    // adj list for all nodes 1..n
    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;
    };

    // For tracking S to U adjacency counts
    vector< vector<int> > UneighborsOfS(n + 1);
    UneighborsOfS.assign(n + 1, {});

    // First handle deg1 U: rbits[u] equals some S code
    vector<char> isDeg1U(n + 1, 0);
    vector<char> isDeg2U(n + 1, 0);
    vector< array<int, 2> > N_S_of_U(n + 1); // store S neighbors for each U (1 or 2)
    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);
        }
    }

    // Handle deg2 U: decode pair of S using zero-bit intersection
    // Precompute pre-allocated arrays to avoid realloc
    vector<uint64_t> cand(WC);
    for (int u : Ulist) {
        if (isDeg1U[u]) continue;
        uint64_t r = rbits[u];
        // Build candidate bitset: indices i of S such that for all j where r bit is 0, codeS[i] bit j is 0
        // Start with all ones
        for (int w = 0; w < WC; ++w) cand[w] = ~0ULL;
        // Apply last word mask
        cand[WC - 1] &= lastMask;
        for (int j = 0; j < K; ++j) {
            if (((r >> j) & 1ULL) == 0ULL) {
                // intersect with BitsZero[j]
                const vector<uint64_t>& bz = BitsZero[j];
                for (int w = 0; w < WC; ++w) cand[w] &= bz[w];
            }
        }
        // Extract candidate S indices
        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;
            }
        }
        // Among candidates, find pair whose OR equals r
        int s1 = -1, s2 = -1;
        if (candidates.size() == 1) {
            // This would imply deg1, but we already handled those
            // As fallback, set s1 to the single candidate, but we need two neighbors; we will try to find second by scanning Slist (rare).
            int idx = candidates[0];
            uint64_t c1 = codeS[idx];
            // find s2: codeS[idx2] such that c1 | codeS[idx2] == r
            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) {
                // give up and mark as deg1 erroneously; connect only one neighbor
                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) {
                // As a fallback (very rare), try scanning all S for a matching pair with size-limited tries
                // We will try to find any s1 in candidates and s2 in S
                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) {
                    // Very unlikely: fall back to arbitrary two from candidates if at least 2
                    if (candidates.size() >= 2) {
                        s1 = Slist[candidates[0]];
                        s2 = Slist[candidates[1]];
                    } else {
                        // give up: connect to nothing; will fail later
                        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 {
                // treat as deg1 fallback
                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 {
            // completely failed; skip
        }
    }

    // Step D: Pair deg1 U nodes using matching via group tests
    // Identify deg1 U list
    vector<int> Udeg1;
    for (int u : Ulist) if (isDeg1U[u]) Udeg1.push_back(u);

    // Turn off all S nodes (to avoid interference)
    {
        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);
        }
    }

    // Build T: a maximal independent set among deg1 U nodes (graph is disjoint edges, but unknown)
    vector<char> inT(n + 1, 0);
    vector<int> Tlist;
    Tlist.reserve(Udeg1.size() / 2 + 1);
    for (int u : Udeg1) {
        // try to add u
        vector<int> res1 = Interactor::query(vector<int>{u});
        int r = res1[0];
        if (r == 0) {
            // keep u on
            inT[u] = 1;
            Tlist.push_back(u);
            isOn[u] = 1;
        } else {
            // revert
            vector<int> res2 = Interactor::query(vector<int>{u});
            isOn[u] = 0;
            (void)res2;
        }
    }

    // Now Tlist is an independent set among deg1 U nodes, so exactly one per matched pair.
    // For each v not in T (but in deg1), find partner in T using log rounds with codes
    int Tcnt = (int)Tlist.size();
    if (Tcnt > 0) {
        int KT = 0;
        while ((1 << KT) < Tcnt) ++KT;
        KT = max(KT, 1); // at least 1 round
        // Assign codes to T elements (use KT bits of a random 64-bit, but we just use lower KT bits)
        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();
            // ensure uniqueness on lower KT bits might not be guaranteed; better use full 64 bits and map
            // But rbits will gather only KT bits; Adjust: we can use KT bits of individual's index to avoid collisions.
            // Let's instead set code = i (on KT bits).
            c = (uint64_t)i;
            codeT[Tlist[i]] = c;
            code2T[c] = Tlist[i];
        }

        vector<uint64_t> rT(n + 1, 0);
        // For each of KT bits, perform test: keep set A_j = { u in T | bit j of code is 1 }, remove others
        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());
            // remove R
            for (int x : R) { ops.push_back(x); isOn[x] = 0; }
            // For each v not in T: toggle v on/off
            for (int v : Udeg1) if (!inT[v]) { ops.push_back(v); ops.push_back(v); }
            // restore R
            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);
            }
            // skip restore responses if needed; not used
        }

        // Now decode partner for each v not in T
        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
                add_edge(u, v);
            } else {
                // fallback: if not found (unlikely), try nearest index
                // We'll compute idx round
                uint64_t idx = code & ((1ULL << KT) - 1ULL);
                int u = Tlist[(int)(idx % Tcnt)];
                add_edge(u, v);
            }
        }

        // Turn off all T nodes to clean up (not necessary, but ensure consistent end state)
        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);
        }
    }

    // Now all adjacencies should be complete: each node should have degree 2
    // For S nodes, ensure they have two U neighbors
    // For deg1 U nodes, they should have 2 neighbors (one S and one deg1 U partner)
    // For deg2 U nodes, they should have 2 neighbors (two S)

    // As a sanity check, if some node has deg < 2, we won't fix; assume good.

    // Build ring ordering by traversing adjacency
    vector<int> ring;
    ring.reserve(n);
    int start = 1;
    // Ensure degree 2 for start; if not, find a node with deg==2
    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) {
            // fail, try to find any not visited node
            // fallback: simple listing
            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);
    }

    // Output the permutation (any rotation or reversal is accepted)
    cout << -1;
    for (int x : ring) cout << " " << x;
    cout << endl;
    cout.flush();
    return 0;
}