交互題,看數據範圍,鐵定二分。設這n個元素最大值爲mx。
問每個集合的補集最大值,顯然,要麼全是mx,要麼只有一個不是mx。
(最大值在某個集合裏,那其他集合的補集最大值一定是mx,這個集合的補集最大值再單獨進行依次詢問即可。(有可能其他集合也有mx))
所以先第一次詢問mx,然後花10次詢問mx最小的id。然後遍歷判斷是否有集合中含有id,如果都沒有,顯然結果都是mx。
如果其中一個含有mx,則詢問這個集合的補集最大值即可。最多12次詢問。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e3+7;
int vs[M];
void ask(int l,int r)
{
cout<<"? "<<r-l+1;for(int i=l;i<=r;i++)cout<<" "<<i;cout<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
vector<int>s[1100];
int n,k;
cin>>n>>k;
for(int i=1;i<=k;i++)
{
int m,x;cin>>m;
for(int j=1;j<=m;j++)cin>>x,s[i].pb(x);
}
ask(1,n);
int mx;
cin>>mx;
int l=1,r=n;
while(l<r)
{
int mid=(l+r)/2;
ask(l,mid);
int tp;
cin>>tp;
if(tp==mx)r=mid;
else l=mid+1;
}
bool f=false;
int id,p;
for(int i=1;i<=k;i++)
{
for(auto x:s[i])
{
if(x==l)
{
id=i;
f=true;
break;
}
}
if(f)break;
}
for(int i=1;i<=n;i++)vs[i]=0;
for(auto x:s[id])vs[x]=1;
cout<<"?";
int nm=0;
for(int i=1;i<=n;i++)if(!vs[i])nm++;
cout<<" "<<nm;
for(int i=1;i<=n;i++)if(!vs[i])cout<<" "<<i;
cout<<endl;
cin>>p;
cout<<"!";
for(int i=1;i<=k;i++)
{
if(i!=id)cout<<" "<<mx;
else cout<<" "<<p;
}
cout<<endl;
string z;
cin>>z;
}
return 0;
}