CF2155D
Solution
这种交互题,一般可以先试着按顺序问。
比如现在知道 $1\rarr i-1$ 和 $1\rarr i$ 的答案 $res_1$ 和 $res_2$。
如果 $res_1=res_2$,说明 $a_i$ 这个数是出现的第一次,否则就是第二次出现了 $a_i$,就记录一下。
但是如果这个 $a_i$ 不够大可能不会显示出来,所以我们需要保证如果 $a_i$ 是第二次出现,那么后面的询问就不再问 $i$ 这个位置,这样就避免了大小的问题,因为不会出现其它的两个相同的数了。
这里已经是 $2\times n$ 次询问了,还有 $n$ 次,一般交互题是要把次数用完的哦。
但是还不知道每个数的第一次在哪里出现,就可以对于每个不是第二次出现的数的位置,一共 $n$ 个,询问一下,同时询问所有出现第二次出现的数的位置,一定会匹配一个,就可以找到了。
Code
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
void solve(){
LL n;
cin >> n;
vector<LL> res(n*2+5),app(n*2+5,0),second(n+5,0);
LL num=1,la=0;
for(int i=2;i<=n*2;i++){
cout<<"? "<<num+1<<' ';
for(int j=1;j<=i;j++){
if(!app[j]) cout<<j<<' ';
}
cout<<"\n";
cout.flush();
LL x;
cin>>x;
if(x==la||x==0) num++;
else app[i]=1,second[x]=i,res[i]=x;
la=x;
}
num=0;
for(int i=1;i<=n*2;i++){
if(app[i]) continue;
cout<<"? "<<n+1<<' ';
for(int i=1;i<=n;i++) cout<<second[i]<<' ';
cout<<i<<endl;
LL x;
cin>>x;
res[i]=x;
cout.flush();
}
cout << "!";
for(int i = 1; i <= 2*n; i++){
cout << " " << res[i];
}
cout << endl;
cout.flush();
}
int main(){
int t;
cin >> t;
while(t--) solve();
return 0;
}