鱼香rose'Blog

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

思路

  1. 首先考虑结果,易知:当\(p_j\)\(n-1\)时,\(p_i\)\(!(p_j)\)时,\({\color{Red} p_i~XOR~p_j}\)的值最大。
  2. 所以我们可以用? a a b b,在\(n\)次内找出最大值的下标,即\(p_j\)\(j\)
  3. 然后我们用? j mx j i,在\(n\)次内找出所有与\(p_j\)进行或运算之后的最大值下标
  4. 然后我们枚举所有的下标,找出最小的\(p_i\),即为所求。
  5. 易证:所有与\(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();
}
posted @ 2026-01-15 21:52  鱼香_rose  阅读(0)  评论(0)    收藏  举报