C o d e f o r c e s R o u n d 930 ( C . B i t w i s e O p e r a t i o n W i z a r d ) \Huge{Codeforces\ Round\ 930(C.Bitwise Operation Wizard)} Codeforces Round 930(C.BitwiseOperationWizard)
文章目录
- 题意
- 思路
- 注意
- 标程
题目链接:[B.Bitwise Operation Wizard](Problem - C - Codeforces)
本题是一道交互题,好久没做交互题了,记录一下。
题意
给出一个长度为 n n n的 ( 0 , n − 1 ) (0,n-1) (0,n−1)的排列组合序列,要求找到下标 i , j i,j i,j,使得 p i X O R p j {\color{Red} p_i~XOR~p_j} pi XOR pj的值最大。
其中,题目给出不超过 3 n 3n 3n次查询:
查询格式为:? a b c d
( 0 ≤ a , b , c , d < n 0 \le a,b,c,d < n 0≤a,b,c,d<n)
返回为: x = ( p a ∣ p b ) x = (p_a \mid p_b) x=(pa∣pb) 和 y = ( p c ∣ p d ) y = (p_c \mid p_d) y=(pc∣pd),返回字符 ′ < ′ , ′ > ′ , ′ = ′ '<','>','=' ′<′,′>′,′=′分别对应 x < y , x > y , x = y x<y,x>y,x=y x<y,x>y,x=y三种情况。
最后输出结果:! i j
。
思路
- 首先考虑结果,易知:当 p j p_j pj为 n − 1 n-1 n−1时, p i p_i pi为 ! ( p j ) !(p_j) !(pj)时, p i X O R p j {\color{Red} p_i~XOR~p_j} pi XOR pj的值最大。
- 所以我们可以用
? a a b b
,在 n n n次内找出最大值的下标,即 p j p_j pj的 j j j。 - 然后我们用
? j mx j i
,在 n n n次内找出所有与 p j p_j pj进行或运算之后的最大值下标。 - 然后我们枚举所有的下标,找出最小的 p i p_i pi,即为所求。
- 易证:所有与 p j p_j pj进行或运算后的结果相等的数字中,最小的数与 p j p_j pj进行 X O R XOR 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();
}