一、题目
二、解法
题目主要在于理解:请求出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);
else
work(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;
}
}