专栏文章

题解:CF2159A MAD Interactive Problem

CF2159A题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minlu5q1
此快照首次捕获于
2025/12/02 04:31
3 个月前
此快照最后确认于
2025/12/02 04:31
3 个月前
查看原文

题解:CF2159A MAD Interactive Problem

关于交互题
每次输出完成之后需要刷新缓存区。为了刷新缓存区并换行,可以直接输出 std::endl

分析题意

需要我们求得的 aa 数组是一个长度为 2n2n,且 1n1 \sim n 在数组中严格出现 22 次。
每次提问需要给出提问的下标,然后交互库会返回这些下标的 MAD 值。MAD 值的定义在题面已经给出。
接下来分析这个条件:1n1 \sim n 在数组中严格出现 22 次。那么我们可以构建两个集合 KKUU,其中 KK 中为对应值确定的下标,UU 中为对应值不确定的下标。我们还需要一个答案数组 ans 来存储最终的答案。
最开始,下标 11 一定在集合 UU 中。接下来从 22 开始遍历下标 ii 直到 2n2n,每次查询集合 UU 中的所有元素和 ii。再读取交互库返回的值 xx,如果 x0x \not = 0,则可以得出 ans[i] = x,并将 ii 加入到集合 KK 中。否则 ans[i] 不确定,并将 ii 加入到集合 UU 中。易证不会有其他情况。
这一步执行完会提问 2n12n - 1 次。
接下来,从 11 开始遍历下标 ii 直到 2n2n。如果下标 ii 在集合 UU 内,此时查询集合 KK 中的所有元素和 ii,并读取交互库返回的结果 xx,则 ans[i] = x。由于在 KK 中的元素对应的值不会重复出现,且元素对应的值严格包含 1n1 \sim n,所以正确性显然。
当第一步执行完时,集合 KK 与集合 UU 中元素的数量一定都为 nn,所以这一步执行完会提问 nn 次。
最后一共提问 3n13n - 1 次,严格小于 3n3n

代码

CPP
#include <bits/stdc++.h>

using namespace std;

void solve(){
    int n;
    cin >> n;
    vector <int> known, unknown, ans(2 * n + 1);//known 对应集合 K,unknown 对应集合 U
    unknown.emplace_back(1);
    for(int i = 2; i <= 2 * n; i++){
        cout << "? " << unknown.size() + 1 << ' ';
        for(const auto &v : unknown)
            cout << v << ' ';
        cout << i << endl;
        int x;
        cin >> x;
        if(x)
            ans[i] = x, known.emplace_back(i);
        else
            unknown.emplace_back(i);
    }
    for(int i = 1; i <= 2 * n; i++){
        if(!ans[i]){
            cout << "? " << known.size() + 1 << ' ';
            for(const auto &x : known)
                cout << x << ' ';
            cout << i << endl;
            int x;
            cin >> x;
            ans[i] = x;
        }
    }
    cout << "! ";
    for(int i = 1; i <= 2 * n; i++)
        cout << ans[i] << " \n"[i == 2 * n];
}

int main(){
    int t;
    cin >> t;
    while(t--)
        solve();
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...