CF1147E Rainbow Coins
题意
有 \(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);
}
}