[Codeforces1491F]Magnets(交互)

题面

分析

从小到大询问([1,i-1])(i),若答案不为0,则(i)为第二个有磁性的磁体。找到这个磁体后,我们可以对(i)后面的位置和(i)单独询问,进而得到后面的所有磁性
然后在([1,i-1])中二分出第一个磁体的位置,剩下的都是没有磁性的。

总询问次数为(n-1+ lceil log_2 n ceil leq n+lfloor log_2 n floor)

代码

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int Ask(int fr,int ed,int pos){
	int ans;
	printf("? %d %d 
",ed-fr+1,1);
	for(int j=fr;j<=ed;j++) printf("%d ",j);
	printf("
%d
",pos);
	fflush(stdout);
	scanf("%d",&ans);
	return ans;
}
void print(vector<int>v){
	printf("! %d
",(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;
			}
		}
	}
}
版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢
原文地址:https://www.cnblogs.com/birchtree/p/14463560.html