# - Make k buckets of approximately equal size # - Find the best in each bucket naively ("candidates") # - Repeat k times: # - Find the best of the k candidates naively # - Grab the next best from the corresponding bucket naively # as a new candidate # # Total interactions (approx): n + k * (k + n/k) = 2n + k^2 n, k = map(int, input().split()) def query(a, b): print(f"? {a} {b}", flush=True) res = int(input()) return res == a def finish(ans): ans_str = " ".join(map(str, ans)) print(f"! {ans_str}", flush=True) exit(0) def best_in_bucket(bucket, eliminated): best_idx = None for idx, val in enumerate(bucket): if val in eliminated: continue if best_idx is None or query(val, bucket[best_idx]): best_idx = idx return None if best_idx is None else bucket[best_idx] buckets = [[] for _ in range(k)] for i in range(1, n+1): buckets[i % k].append(i) eliminated = set() candidates = [best_in_bucket(bucket, eliminated) for bucket in buckets] answer = [] while len(answer) < k: best = best_in_bucket(candidates, eliminated) best_bucket_idx = best % k answer.append(best) eliminated.add(best) new_candidate = best_in_bucket(buckets[best_bucket_idx], eliminated) if new_candidate is not None: candidates.append(new_candidate) finish(answer)