[CF1267I] Intriguing Selection 题解
考虑 的情况,假设我们第一次询问 ,得到 ,如果第二次询问仍然包含 的话就可能得到前 名的排序了。
接着询问 不好做,于是我们考虑询问另一个不相交的 ,得到 ,我们再询问一次 的大小关系,不妨设 ,此时我们可以询问 与其他所有人的大小关系,因为存在两个比它大的大小关系不确定。
考虑这样一个算法,我们维护一个初始包含所有数的队列,每次依次取出 四个数,按照如上方法询问,之后再按 的顺序放回,这样一直做到只剩三个数为止,此时我们一定能保证这三个数中我们只知道一对的大小关系,结束即可。
#include <bits/stdc++.h>
using namespace std;
int n, mp[210][210];
int query(int a, int b) {
if (mp[a][b] != -1)
return mp[a][b];
cout << "? " << a << " " << b << '\n';
cout.flush();
char c;
cin >> c;
return mp[a][b] = c == '<';
}
int main() {
cin.tie(0)->sync_with_stdio(0);
int T;
cin >> T;
while (T--) {
cin >> n;
n <<= 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
mp[i][j] = -1;
vector<int> v;
for (int i = 1; i <= n; i++)
v.push_back(i);
while (v.size() > 3) {
int a = v.back();
v.pop_back();
int b = v.back();
v.pop_back();
int c = v.back();
v.pop_back();
int d = v.back();
v.pop_back();
if (!query(a, b))
swap(a, b);
if (!query(c, d))
swap(c, d);
if (!query(a, c))
swap(a, c), swap(b, d);
for (int i = 1; i <= n; i++) {
if (i != a)
query(i, a);
}
v.push_back(b), v.push_back(c), v.push_back(d);
}
cout << "! " << '\n';
cout.flush();
}
return 0;
}
// 1 6 4 3 2 5

浙公网安备 33010602011771号