一、题目
点此看题
二、解法
题目主要在于理解:请求出max{a[j]},其中j不属于Si
我们可以先求出整个序列的最大值,对于不包含这个的集合答案都可以确定了,如果有集合包含这个最大值,再做一次询问就行了,求最大值可以二分。
还有细节,康康代码。
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
const int M = 1005;
int T,n,m,k,x,flag[M],a[M];
vector<int> s[M];string str;
int ask(int l,int r)
{cout<<"? "<<r-l+1;for(int i=l;i<=r;i++) cout<<" "<<i;cout<<endl;int t;cin>>t;return t;
}
void work(int l,int r)
{if(l==r) {k=l;return ;}int mid=(l+r)>>1;if(ask(l,mid)==x)work(l,mid);elsework(mid+1,r);
}
signed main()
{//freopen("1.out","w",stdout);cin>>T;while(T--){cin>>n>>m;for(int i=1;i<=n;i++)flag[i]=0;for(int i=1,t;i<=m;i++){cin>>t;s[i].clear();while(t--){int shit;cin>>shit;s[i].push_back(shit);}}x=ask(1,n);work(1,n);for(int i=1;i<=m;i++){int f=0;for(int j=0;j<s[i].size();j++)if(s[i][j]==k){f=1;break;}if(f==0) a[i]=x;else{cout<<"? "<<n-s[i].size();for(int j=0;j<s[i].size();j++)flag[s[i][j]]=1;for(int j=1;j<=n;j++)if(!flag[j])cout<<" "<<j;cout<<endl;cin>>a[i];}}printf("!");for(int i=1;i<=m;i++)cout<<" "<<a[i];cout<<endl;cin>>str;}
}