codeforces930(C
\(\Huge{Codeforces\ Round\ 930(C.Bitwise Operation Wizard)}\)
题目链接:[B.Bitwise Operation Wizard](Problem - C - Codeforces)
本题是一道交互题,好久没做交互题了,记录一下。
题意
给出一个长度为\(n\)的\((0,n-1)\)的排列组合序列,要求找到下标\(i,j\),使得\({\color{Red} p_i~XOR~p_j}\)的值最大。
其中,题目给出不超过\(3n\)次查询:
查询格式为:? a b c d (\(0 \le a,b,c,d < n\))
返回为:\(x = (p_a \mid p_b)\) 和 \(y = (p_c \mid p_d)\),返回字符\('<','>','='\)分别对应\(x<y,x>y,x=y\)三种情况。
最后输出结果:! i j。
思路
- 首先考虑结果,易知:当\(p_j\)为\(n-1\)时,\(p_i\)为\(!(p_j)\)时,\({\color{Red} p_i~XOR~p_j}\)的值最大。
- 所以我们可以用
? a a b b,在\(n\)次内找出最大值的下标,即\(p_j\)的\(j\)。 - 然后我们用
? j mx j i,在\(n\)次内找出所有与\(p_j\)进行或运算之后的最大值下标。 - 然后我们枚举所有的下标,找出最小的\(p_i\),即为所求。
- 易证:所有与\(p_j\)进行或运算后的结果相等的数字中,最小的数与\(p_j\)进行\(XOR\)运算结果最大。
注意
在交互题中,交互过程中的输入输出需要刷新输入输出,c/c++通常使用fflush(stdout)或cout.flush()。
标程
char query(int a, int b, int c, int d) {
char ch;
cout << "? " << a <<' '<< b <<' '<< c <<' '<< d << endl;
cout.flush();
cin >> ch;
cout.flush();
return ch;
}
void Solved() {
int n; cin >> n;
int res1 = 0, res2 = 0, mx = 0;
vector<int> a;
for(int i = 1; i < n; i ++ ) {
char ch = query(res1, res1, i, i);
if(ch == '<') res1 = i;
}
a.push_back(0);
for(int i = 1; i < n; i ++ ) {
char ch = query(mx, res1, i, res1);
if(ch == '<') {
mx = i; a.clear(); a.push_back(i);
}
if(ch == '=') a.push_back(i);
}
res2 = a.front();
for(int i = 1; i < a.size(); i ++ ) {
char ch = query(res2, res2, a[i], a[i]);
if(ch == '>') res2 = a[i];
}
cout << "! " << res1 << ' ' << res2 << endl;
cout.flush();
}

浙公网安备 33010602011771号