题解 CF1270D 【Strange Device】

xht

2019-12-30 23:38:40

Solution

交互题。 首先可以通过 $n-k+1$ 次询问确定 $n-k+1$ 个位置的值。 若 $n - k + 1 \ge k$,则直接询问已知的 $k$ 个找到 $m$ 即可。 否则,考虑最后一次询问会产生一个已知的位置 $x$ 和 $k-1$ 个未知的位置,我们可以拿另外一个已知的位置 $y$ 分别替换这 $k-1$ 个未知的位置,然后根据回答与不替换时的回答是否一致判断这个位置与 $x$ 位置上的数的大小关系,即可找到这些数中有多少个比位置 $x$ 上的数小,从而求出 $m$。 ```cpp const int N = 507; int n, k, a[N]; inline pi ask(vi o) { vi O = o; sort(o.begin(), o.end()); cout << '?'; for (auto c : o) cout << ' ' << c; cout << endl; fflush(stdout); int a, b; cin >> a >> b; o = O; return mp(a, b); } int main() { cin >> n >> k; if (k == 1) return cout << "! 1" << endl, 0; vi o, q; for (int i = 1; i <= k; i++) o.pb(i); for (int i = k; i <= n; i++) { pi p = ask(o); a[p.fi] = p.se; q.pb(p.fi); if (i != n) for (ui j = 0; j < o.size(); j++) if (o[j] == p.fi) o[j] = i + 1; } if (n - k + 1 >= k) { o.clear(); for (int i = 0; i < k; i++) o.pb(q[i]); pi p = ask(o); int ans = 0; for (int i = 0; i < k; i++) if (a[o[i]] <= p.se) ++ans; cout << "! " << ans << endl; return 0; } int x = q.back(); q.pop_back(); int y = q.back(); for (ui i = 1; i < o.size(); i++) if (o[i] == x) swap(o[0], o[i]); int ans = 0; for (ui i = 1; i < o.size(); i++) { int z = o[i]; o[i] = y; pi p = ask(o); if (p.fi == x) ans += a[y] < a[x]; else ans += a[x] < a[y]; o[i] = z; } cout << "! " << ans + 1 << endl; return 0; } ```