CF1147E Rainbow Coins

洛谷传送门 CF传送门

题意

\(n\) 个硬币,每个硬币有一种颜色,是R,G,B中的一种。可以选择两个硬币进行询问颜色是否一样,每次可以同时询问若干对硬币(一个硬币不能同时属于两对)。最多7次询问,将硬币分为颜色不同的三组。

Solution

这是个思维很棒的交互题。

我们可以先询问两次:

1.第一次询问 \(2i-1,2i\rightarrow 1 2|3 4|56 |\cdots\)

2.第二次询问 \(2i,2i+1\rightarrow 23|45|67|\cdots\)

这样做可以得到两边相邻的颜色是否一样。

如果一样,就将他们合并。设合并完用 \(now\) 表示,那么此时对于 \(now_i\)\(now_{i-1},now_{i+1}\) 和它的颜色都不一样。

但是 \(now_{i-1},now_{i+1}\) 之间的关系我们还不知道,所以还要询问两次:

1.第三次询问 \(now_{i-2},now_{i}\)

2.第四次询问 \(now_i,now_{i+2}\)

此时我们对于所有硬币之间的关系就都知道了,然后扫一遍求答案即可

Code

#include<bits/stdc++.h>
#define PII pair<int,int>

using namespace std;
const int N=100010;
int T,n,cnt,now[N],ans[N];
char ch[N];
vector<int>A,B,C;
map<PII,bool>col;

inline void ask(){
    if(!A.size()) return ;
    printf("Q %d ",(int)A.size());
    for(int i=0;i<A.size();i++) printf("%d %d ",A[i],B[i]);
    puts("");
    fflush(stdout);
    scanf("%s",ch+1);
    for(int i=0;i<A.size();i++) col[make_pair(A[i],B[i])]=(ch[i+1]=='1');
}

int main(){
    scanf("%d",&T);
    while(T--){
        cnt=0;col.clear();
        memset(ans,0,sizeof(ans));
        scanf("%d",&n);
        A.clear();B.clear();
        for(int i=2;i<=n;i+=2){
            A.push_back(i-1);
            B.push_back(i);
        }
        ask();
        A.clear();B.clear();
        for(int i=3;i<=n;i+=2){
            A.push_back(i-1);
            B.push_back(i);
        }
        ask();
        now[++cnt]=1;
        for(int i=2;i<=n;i++)
            if(!col[make_pair(i-1,i)]) now[++cnt]=i;
        A.clear();B.clear();
        for(int i=3;i<=cnt;i+=4) A.push_back(now[i-2]),B.push_back(now[i]);
        for(int i=4;i<=cnt;i+=4) A.push_back(now[i-2]),B.push_back(now[i]);
        ask();
        A.clear();B.clear();
        for(int i=3;i<=cnt-2;i+=4) A.push_back(now[i]),B.push_back(now[i+2]);
        for(int i=4;i<=cnt-2;i+=4) A.push_back(now[i]),B.push_back(now[i+2]);
        ask();
        ans[now[1]]=1;
        if(cnt>1) ans[now[2]]=2;
        for(int i=3;i<=cnt;i++){
            if(col[make_pair(now[i-2],now[i])]) ans[now[i]]=ans[now[i-2]];
            else ans[now[i]]=6-ans[now[i-2]]-ans[now[i-1]];
        }
        A.clear();B.clear();C.clear();
        for(int i=1,t;i<=n;i++){
            if(ans[i]) t=ans[i];
            ans[i]=t;
            if(ans[i]==1) A.push_back(i);
            else if(ans[i]==2) B.push_back(i);
            else if(ans[i]==3) C.push_back(i);
        }
        printf("A %d %d %d\n",(int)A.size(),(int)B.size(),(int)C.size());
        for(int i=0;i<A.size();i++) printf("%d ",A[i]);
        puts("");
        for(int i=0;i<B.size();i++) printf("%d ",B[i]);
        puts("");
        for(int i=0;i<C.size();i++) printf("%d ",C[i]);
        puts("");
        fflush(stdout);
    }
}
posted @ 2020-10-25 14:44  jasony_sam  阅读(94)  评论(0编辑  收藏  举报