File size: 14,197 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
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
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;

static char obuf[1<<22]; static int opos;
void oflush(){fwrite(obuf,1,opos,stdout);opos=0;fflush(stdout);}
void ochar(char c){obuf[opos++]=c;}
void oint(int x){
    if(x>=1000){ochar('0'+x/1000);ochar('0'+(x/100)%10);ochar('0'+(x/10)%10);ochar('0'+x%10);}
    else if(x>=100){ochar('0'+x/100);ochar('0'+(x/10)%10);ochar('0'+x%10);}
    else if(x>=10){ochar('0'+x/10);ochar('0'+x%10);}
    else ochar('0'+x);
}

int N,q[1001],perm[1001];
int kc;

int ask(){ochar('0');for(int i=0;i<N;i++){ochar(' ');oint(q[i]);}ochar('\n');oflush();int x;scanf("%d",&x);return x;}
void submit(){ochar('1');for(int i=0;i<N;i++){ochar(' ');oint(perm[i]);}ochar('\n');oflush();exit(0);}

// Determine which half (left=true, right=false) each value's position is in.
// vals: values to assign. pos: positions, split at 'half' (left=[0..half-1], right=[half..n-1]).
// Returns: for each value in vals, true if in left half, false if in right half.
void assign_halves(vector<int>& vals, vector<int>& pos, int half, vector<bool>& is_left) {
    int n = vals.size();
    is_left.resize(n);

    // Phase 1: pair up values and do paired queries
    // Track same-half pairs for batched disambiguation
    vector<int> determined; // indices into vals that are determined
    vector<pair<int,int>> same_half_pairs; // pairs of indices that are in the same half

    int vi = 0;
    while (vi < n) {
        if (vi + 1 >= n) {
            // Odd value out - query directly
            int v = vals[vi];
            for (int i = 0; i < half; i++) q[pos[i]] = v;
            int r = ask();
            for (int i = 0; i < half; i++) q[pos[i]] = 1;
            is_left[vi] = (r == kc + 1);
            vi++;
            continue;
        }

        int v = vals[vi], w = vals[vi + 1];
        // Paired query: left=v, right=w
        for (int i = 0; i < half; i++) q[pos[i]] = v;
        for (int i = half; i < (int)pos.size(); i++) q[pos[i]] = w;
        int r = ask();
        for (int i = 0; i < half; i++) q[pos[i]] = 1;
        for (int i = half; i < (int)pos.size(); i++) q[pos[i]] = 1;

        if (r == kc + 2) {
            is_left[vi] = true;
            is_left[vi + 1] = false;
        } else if (r == kc) {
            is_left[vi] = false;
            is_left[vi + 1] = true;
        } else {
            // Same half - defer disambiguation
            same_half_pairs.push_back({vi, vi + 1});
        }
        vi += 2;
    }

    // Phase 2: Batch disambiguation of same-half pairs.
    // Each pair (i,j) means vals[i] and vals[j] are in the same half.
    // We need to determine which half.
    // Strategy: pair up these pairs and use paired queries on representatives.

    while (!same_half_pairs.empty()) {
        vector<pair<int,int>> next_round;

        int si = 0;
        while (si < (int)same_half_pairs.size()) {
            if (si + 1 >= (int)same_half_pairs.size()) {
                // Odd pair - query directly
                auto [i, j] = same_half_pairs[si];
                int v = vals[i];
                for (int k = 0; k < half; k++) q[pos[k]] = v;
                int r = ask();
                for (int k = 0; k < half; k++) q[pos[k]] = 1;
                bool left = (r == kc + 1);
                is_left[i] = left;
                is_left[j] = left;
                si++;
                continue;
            }

            // Pair two same-half pairs and query
            auto [i1, j1] = same_half_pairs[si];
            auto [i2, j2] = same_half_pairs[si + 1];
            int v = vals[i1], w = vals[i2];

            // Paired query: left=v, right=w
            for (int k = 0; k < half; k++) q[pos[k]] = v;
            for (int k = half; k < (int)pos.size(); k++) q[pos[k]] = w;
            int r = ask();
            for (int k = 0; k < half; k++) q[pos[k]] = 1;
            for (int k = half; k < (int)pos.size(); k++) q[pos[k]] = 1;

            if (r == kc + 2) {
                // v in left, w in right
                is_left[i1] = true; is_left[j1] = true;
                is_left[i2] = false; is_left[j2] = false;
            } else if (r == kc) {
                // v in right, w in left
                is_left[i1] = false; is_left[j1] = false;
                is_left[i2] = true; is_left[j2] = true;
            } else {
                // Same half again! All 4 values in same half.
                // Group them: (i1,j1,i2,j2) all in same half.
                // For next round, treat as a single "super pair" with representative i1.
                // Actually, just pair them again: one representative per group.
                // We know i1,j1,i2,j2 all in same half.
                // Create a new pair entry for the next round.
                // Use i1 as representative for the group of 4.
                // Store all 4 indices somewhere.
                // Actually, let's just store one representative per group and a list of dependents.
                // For simplicity, just re-add (i1, i2) as a pair with j1,j2 as dependents.
                // When we determine i1's half, set j1,i2,j2 to the same.

                // Simple approach: mark j1 and j2 as depending on i1 and i2 respectively.
                // But they're already co-located. Let me just re-add as a single group.

                // For the next round, (i1, i2) is a same-half pair.
                // i1 carries j1 as a dependent. i2 carries j2.
                // When i1's half is determined, so is j1, i2, j2.

                // Simplest: just track that i1 and i2 are in the same half.
                // j1 and j2 are already known to be in the same half as i1 and i2 respectively.
                // So all 4 are in the same half.
                // Add (i1, i2) to next_round. When resolved, set all 4.

                // But we need to propagate: when i1 is determined, also set j1, i2, j2.
                // This requires tracking the groups.

                // Simplest implementation: use Union-Find to group all co-half values.
                // Then in each round, pick one representative per group and pair them.

                next_round.push_back({i1, i2});
                // All 4 will be in the same half. When (i1,i2) is resolved in a future round,
                // we need is_left[i1]=is_left[j1]=is_left[i2]=is_left[j2].
                // Since j1 is already linked to i1 and j2 to i2, we just need i1 and i2 to be resolved.
                // In the next round, (i1,i2) is a same-half pair. When it's determined,
                // is_left[i1] = is_left[i2] = some value. Then j1 and j2 also get that value.

                // But wait, is_left[j1] should already be set to the same as is_left[i1] from the original same_half_pairs entry.
                // Hmm, is_left[j1] hasn't been set yet (it's uninitialized for same_half entries).
            }
            si += 2;
        }
        same_half_pairs = next_round;
    }

    // Now propagate: for each original same-half pair (i,j), set is_left[j] = is_left[i].
    // But the propagation is implicit in the batched resolution above.
    // Wait - I only set is_left for the FIRST index of each pair when resolving.
    // Need to also set the second index.
    // Actually, in the code above, when we resolve a pair (i1,i2) from the next_round,
    // we set is_left[i1] and is_left[i2] directly. And the j1,j2 from the original pairs
    // are NOT set.

    // BUG: I need to propagate is_left from representatives to all group members.
    // This requires a proper Union-Find or group tracking.
}

// Hmm, this is getting complicated. Let me use Union-Find.

int parent[1001];
int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); }
void unite(int a, int b) { parent[find(a)] = find(b); }

void solve(vector<int>& vals, vector<int>& pos) {
    int n = vals.size();
    if (n == 0) return;
    if (n == 1) {
        perm[pos[0]] = vals[0]; q[pos[0]] = vals[0]; kc++;
        return;
    }
    if (n == 2) {
        q[pos[0]] = vals[0];
        int r = ask();
        q[pos[0]] = 1;
        if (r == kc + 1) {
            perm[pos[0]] = vals[0]; q[pos[0]] = vals[0];
            perm[pos[1]] = vals[1]; q[pos[1]] = vals[1];
        } else {
            perm[pos[0]] = vals[1]; q[pos[0]] = vals[1];
            perm[pos[1]] = vals[0]; q[pos[1]] = vals[0];
        }
        kc += 2;
        return;
    }

    int half = n / 2;

    // Initialize Union-Find for this level
    for (int i = 0; i < n; i++) parent[i] = i;

    // Determine which half each value is in
    vector<int> half_known(n, -1); // -1=unknown, 0=left, 1=right

    // Phase 1: pair values, do paired queries
    vector<int> same_half_reps; // representatives of same-half groups

    // Initial pairing: consecutive pairs
    for (int vi = 0; vi + 1 < n; vi += 2) {
        int v = vals[vi], w = vals[vi + 1];
        for (int i = 0; i < half; i++) q[pos[i]] = v;
        for (int i = half; i < n; i++) q[pos[i]] = w;
        int r = ask();
        for (int i = 0; i < half; i++) q[pos[i]] = 1;
        for (int i = half; i < n; i++) q[pos[i]] = 1;

        if (r == kc + 2) {
            half_known[vi] = 0; half_known[vi + 1] = 1;
        } else if (r == kc) {
            half_known[vi] = 1; half_known[vi + 1] = 0;
        } else {
            // Same half
            unite(vi, vi + 1);
            same_half_reps.push_back(find(vi));
        }
    }

    // Handle odd value
    if (n % 2 == 1) {
        int vi = n - 1;
        int v = vals[vi];
        for (int i = 0; i < half; i++) q[pos[i]] = v;
        int r = ask();
        for (int i = 0; i < half; i++) q[pos[i]] = 1;
        half_known[vi] = (r == kc + 1) ? 0 : 1;
    }

    // Phase 2: Batch disambiguation
    // Deduplicate same_half_reps
    sort(same_half_reps.begin(), same_half_reps.end());
    same_half_reps.erase(unique(same_half_reps.begin(), same_half_reps.end()), same_half_reps.end());

    while (!same_half_reps.empty()) {
        vector<int> next_reps;

        int si = 0;
        while (si < (int)same_half_reps.size()) {
            if (si + 1 >= (int)same_half_reps.size()) {
                // Odd group - query directly
                int rep = same_half_reps[si];
                // Find any value in this group
                int v = -1;
                for (int i = 0; i < n; i++) {
                    if (find(i) == find(rep)) { v = vals[i]; break; }
                }
                for (int k = 0; k < half; k++) q[pos[k]] = v;
                int r = ask();
                for (int k = 0; k < half; k++) q[pos[k]] = 1;
                int h = (r == kc + 1) ? 0 : 1;
                for (int i = 0; i < n; i++) {
                    if (find(i) == find(rep)) half_known[i] = h;
                }
                si++;
                continue;
            }

            int rep1 = same_half_reps[si], rep2 = same_half_reps[si + 1];
            int v = -1, w = -1;
            for (int i = 0; i < n; i++) {
                if (find(i) == find(rep1) && v == -1) v = vals[i];
                if (find(i) == find(rep2) && w == -1) w = vals[i];
                if (v != -1 && w != -1) break;
            }

            for (int k = 0; k < half; k++) q[pos[k]] = v;
            for (int k = half; k < n; k++) q[pos[k]] = w;
            int r = ask();
            for (int k = 0; k < half; k++) q[pos[k]] = 1;
            for (int k = half; k < n; k++) q[pos[k]] = 1;

            if (r == kc + 2) {
                // Group 1 in left, group 2 in right
                for (int i = 0; i < n; i++) {
                    if (find(i) == find(rep1)) half_known[i] = 0;
                    if (find(i) == find(rep2)) half_known[i] = 1;
                }
            } else if (r == kc) {
                for (int i = 0; i < n; i++) {
                    if (find(i) == find(rep1)) half_known[i] = 1;
                    if (find(i) == find(rep2)) half_known[i] = 0;
                }
            } else {
                // Same half again - merge groups
                unite(rep1, rep2);
                next_reps.push_back(find(rep1));
            }
            si += 2;
        }

        sort(next_reps.begin(), next_reps.end());
        next_reps.erase(unique(next_reps.begin(), next_reps.end()), next_reps.end());
        same_half_reps = next_reps;
    }

    // Split into left and right
    vector<int> left_vals, right_vals;
    vector<int> left_pos(pos.begin(), pos.begin() + half);
    vector<int> right_pos(pos.begin() + half, pos.end());

    for (int i = 0; i < n; i++) {
        if (half_known[i] == 0) left_vals.push_back(vals[i]);
        else right_vals.push_back(vals[i]);
    }

    solve(left_vals, left_pos);
    solve(right_vals, right_pos);
}

int main(){
    scanf("%d",&N);
    memset(perm,0,sizeof(perm));
    if(N==1){perm[0]=1;submit();}
    if(N==2){q[0]=1;q[1]=2;if(ask()==2){perm[0]=1;perm[1]=2;}else{perm[0]=2;perm[1]=1;}submit();}

    // Phase 1: Find pos1 and pos3
    int B=0;{int tmp=N-1;while(tmp>0){B++;tmp>>=1;}}
    int rb[12];
    for(int b=0;b<B;b++){
        for(int i=0;i<N;i++) q[i]=(i&(1<<b))?1:3;
        rb[b]=ask();
    }
    int kb1=0,kb3=0,kmask=0;
    for(int b=0;b<B;b++){
        if(rb[b]==0){kmask|=(1<<b);kb3|=(1<<b);}
        else if(rb[b]==2){kmask|=(1<<b);kb1|=(1<<b);}
    }
    int amask=((1<<B)-1)&~kmask,P=0;
    for(int b=0;b<B;b++){
        if(!(amask&(1<<b)))continue;
        for(int i=0;i<N;i++){
            q[i]=((i&(1<<b))&&(i&kmask)==kb1)?1:3;
        }
        int r=ask();
        if(r==2) P|=(1<<b);
    }
    int p1=kb1|(P&amask);
    int p3=kb3|(P&amask);
    if(p1<0||p1>=N||p3<0||p3>=N||p1==p3){
        p1=-1;p3=-1;
        for(int i=0;i<N;i++){
            if(p1>=0&&p3>=0)break;
            for(int j=0;j<N;j++)q[j]=3;q[i]=1;
            int r=ask();
            if(r==2)p1=i;else if(r==0)p3=i;
        }
    }
    perm[p1]=1;perm[p3]=3;
    kc=2;
    for(int i=0;i<N;i++) q[i]=1;
    q[p1]=1;q[p3]=3;

    vector<int> vals,pos;
    vals.push_back(2);
    for(int v=4;v<=N;v++) vals.push_back(v);
    for(int i=0;i<N;i++) if(i!=p1&&i!=p3) pos.push_back(i);

    solve(vals,pos);
    submit();
}