题解:P17854 [LBA-OI R6 B] 凌云沐雨
jhashexcoder · · 题解
注意到当且仅当置换环数量等于集合大小时,答案正确。
进一步注意到允许的询问次数为
分析得:
假设当前已有
若新数实际应该插入第
因此置换环数量为
即询问返回值就是新数应插入的位置。
于是从一个元素开始,每次询问并将新元素插入对应位置,恰好使用
最终得到按值升序排列的下标序列,求逆排列即可得到答案。
时间复杂度
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, k;
cin >> n >> k;
stack<int> a;
for (int i = 1; i <= n; i++) {
a.push(i);
}
vector<int> t1;
vector<int> t2;
t1.push_back(a.top());
a.pop();
while (!a.empty()) {
cout << "? " << t1.size() + 1 << " ";
for (auto i : t1) {
cout << i << " ";
}
cout << a.top() << endl;
int x;
cin >> x;
if (x == -1) {
return 0;
}
int cnt = 0;
for (auto i : t1) {
if (cnt == x - 1) {
t2.push_back(a.top());
}
t2.push_back(i);
cnt++;
}
if (x == t1.size() + 1) {
t2.push_back(a.top());
}
t1.clear();
t1 = t2;
t2.clear();
a.pop();
}
t2.resize(n);
for (int i = 0; i < n; i++) {
t2[t1[i] - 1] = i + 1;
}
t1 = t2;
cout << "! ";
for (auto i : t1) {
cout << i << " ";
}
cout << endl;
return 0;
}
如果不用 endl 记得要手动刷缓冲区。
代码极其屎山,轻喷。