D. Guess The Maximums(简单二分)

D. Guess The Maximums(简单二分)

传送门

思路:题意太迷惑了,它的意思是只要找到一个满足条件的数组 P P P即可,而不是要求跟预设的数字一模一样,真实迷惑,显然二分找到最大元素下标所在集合 S S S.

然后除了 P i P_i Pi其他都为最大元素, P i P_i Pi的求法就是所有集合去掉 S i S_i Si再询问一次最大元素答案就是 P i P_i PiMDZZ

#include
using namespace std;
typedef long long ll;
const int N=1e5+5;
#define mst(a) memset(a,0,sizeof a)
int ask(vector<int>v){
	 cout<<"? "<<v.size()<<" ";
	 for(int i:v)
	 	cout<<i<<" ";
	cout<<endl;
	int x;
	cin>>x;
	return x;
}
vector<int> get_set(vector<int>v,int n){
	  vector<int>s,vis(n+1);
	  for(auto i:v)
	  	   vis[i]=1;
	  for(int i=1;i<=n;i++) if(!vis[i]) s.push_back(i);
	  return s;
}
int main(){
	int t,n,k,c; 
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&k);
		vector<vector<int> >S(k); //如果用了 resize()就不要用 push_back,不然会出错。 
		for(int i=0;i<k;i++){
			 scanf("%d",&c);
			 for(int j=0,x;j<c;j++){
			 	scanf("%d",&x);
			 	S[i].push_back(x);
			}
		}
		vector<int>query;
		for(int  i=1;i<=n;i++) query.push_back(i);
		int mx=ask(query);
		int l=0,r=k-1;
		while(l<r){
			 int mid=(l+r)>>1;
			 vector<int>tmp;
			 tmp.clear();
			 for(int i=0;i<=mid;i++)
			 	for(int j:S[i])
				 	tmp.push_back(j);
			 int x=ask(tmp);
			 if(x==mx) r=mid;
			 else l=mid+1; 
		}
		vector<int>ans(k),other;
		other=get_set(S[l],n);
		for(int i=0;i<k;i++){
			 if(l==i)
			 	ans[i]=ask(other);
			else ans[i]=mx;
		}
		cout<<"! ";
		for(auto i:ans)
			printf("%d ",i);
		cout<<endl;
		string jg;
		cin>>jg;		
	}
	return 0;
} 

你可能感兴趣的:(二分,交互题)