https://codeforces.com/problemset/problem/1363/D
md昨晚卡E卡太久了,這道水題沒時間做了
我平常寫的二分好像都有可能要多問一次,因爲出來以後還要再詢問一次,改成那種邊二分邊記錄答案的寫法就過了
這題就先確定最大值的最靠左的位置在哪裏,然後判斷那裏時候被某個子集包含,如果不被任何子集包含,那麼答案全是mx
否則,再查詢除了這個子集外的全部位置的次大值,就是這個子集的答案,其餘的子集的答案全是mx
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
const int mod=1e9+7;
int n,m,cas,k;
int a[maxl],b[maxl],dy[maxl],ans[maxl];
bool in[maxl];
char ch[maxl];
vector<int> s[maxl];
vector<int> tmp;
inline void prework()
{
int c;
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
{
s[i].clear();
scanf("%d",&c);
s[i].resize(c);
for(int j=0;j<c;j++)
{
scanf("%d",&s[i][j]);
dy[s[i][j]]=i;
}
}
}
inline int qry()
{
int len=tmp.size();
printf("? %d",len);
for(int i=0;i<len;i++)
printf(" %d",tmp[i]);
puts("");
fflush(stdout);
int ret;
scanf("%d",&ret);
return ret;
}
inline void mainwork()
{
tmp.clear();
for(int i=1;i<=n;i++)
tmp.push_back(i);
int mx=qry(),ind=n;
int l=1,r=n-1,mid,now;
while(l<=r)
{
mid=(l+r)>>1;
tmp.clear();
for(int i=1;i<=mid;i++)
tmp.push_back(i);
now=qry();
if(now==mx)
r=mid-1,ind=min(ind,mid);
else
l=mid+1;
}
if(dy[ind]==0)
{
for(int i=1;i<=k;i++)
ans[i]=mx;
return;
}
for(int i=1;i<=k;i++)
if(i!=dy[ind])
ans[i]=mx;
for(int i=1;i<=n;i++)
in[i]=true;
for(int i:s[dy[ind]])
in[i]=false;
tmp.clear();
for(int i=1;i<=n;i++)
if(in[i])
tmp.push_back(i);
ans[dy[ind]]=qry();
}
inline void print()
{
printf("!");
for(int i=1;i<=k;i++)
printf(" %d",ans[i]);
puts("");
fflush(stdout);
scanf("%s",ch+1);
}
int main()
{
int t=1;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}