[Codeforces1491F]Magnets(交互)
题面
略
分析
从小到大询问\([1,i-1]\)与\(i\),若答案不为0,则\(i\)为第二个有磁性的磁体。找到这个磁体后,我们可以对\(i\)后面的位置和\(i\)单独询问,进而得到后面的所有磁性
然后在\([1,i-1]\)中二分出第一个磁体的位置,剩下的都是没有磁性的。
总询问次数为\(n-1+ \lceil log_2 n\rceil \leq n+\lfloor log_2 n \rfloor\)
代码
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int Ask(int fr,int ed,int pos){
int ans;
printf("? %d %d \n",ed-fr+1,1);
for(int j=fr;j<=ed;j++) printf("%d ",j);
printf("\n%d\n",pos);
fflush(stdout);
scanf("%d",&ans);
return ans;
}
void print(vector<int>v){
printf("! %d\n",(int)v.size());
for(int x : v) printf("%d ",x);
fflush(stdout);
}
int T,n;
int main(){
scanf("%d",&T);
while(T--){
vector<int>ans;
scanf("%d",&n);
for(int i=2;i<=n;i++){
if(Ask(1,i-1,i)!=0){//找到第2个有磁性的位置
//用这个磁体确定后面的磁性
for(int j=i+1;j<=n;j++) if(Ask(i,i,j)==0) ans.push_back(j);
int l=1,r=i-1,mid,pos=0;
while(l<=r){//找到第1个有磁性的位置
mid=(l+r)>>1;
if(Ask(1,mid,i)!=0){
pos=mid;
r=mid-1;
}else l=mid+1;
}
for(int j=1;j<pos;j++) ans.push_back(j);
for(int j=pos+1;j<i;j++) ans.push_back(j);
print(ans);
break;
}
}
}
}
版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢