[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;
			}
		}
	}
}
posted @ 2021-03-01 14:47  birchtree  阅读(60)  评论(0编辑  收藏  举报