-
对于位置 \(p_1,p_2\),如果询问除了这两个位置以外的所有位置,如果答案为 \(n/2,n/2+1\),则说明 \(p_1,p_2\) 这两个位置上的元素一个小于 \(n/2\),一个大于 \(n/2+1\)。
-
我们通过随机化选取 \(p_1,p_2\) 以满足这两个位置上的元素一个小于 \(n/2\),一个大于 \(n/2+1\)。
-
考虑另外的两个位置 \(x,y\),如果询问 \(p_1,p_2,x,y\) 的答案其中一个为 \(n/2\),那么 \(x,y\) 中必有一个位置上的元素为 \(n/2\),如果询问 \(p_1,p_2,x,y\) 的答案其中一个为 \(n/2+1\),那么 \(x,y\) 中必有一个位置上的元素为 \(n/2+1\)。
-
记录答案等于 \(n/2\) 或 \(n/2+1\) 的两组 \(x,y\),令为 \(p_3,p_4,p_5,p_6\)。
-
最后只需对 \(p_3,p_4,p_5,p_6\) 两两组合与 \(p_1,p_2\) 一起询问,如果答案为 \(n/2\) 和 \(n/2+1\),就输出这两个 \(p\) 。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n;
mt19937 rnd(time(0));
void sol(){
cin>>n;
ll p1=0,p2=0;
while(1){
ll x,y;
x=rnd()%n+1,y=rnd()%n+1;
while(y==x)y=rnd()%n+1;
cout<<"? "<<n-2<<" ";
for(int j=1;j<=n;j++){
if(j!=x&&j!=y)cout<<j<<" ";
}
cout<<endl;
ll ax,ay;
cin>>ax>>ay;
if(ax==n/2&&ay==n/2+1){
p1=x,p2=y;
break;
}
}
ll x=0,y=0,p3,p4,p5,p6;
while(y<=n){
x++;
while(x==p1||x==p2)x++;
y=x+1;
while(y==p1||y==p2)y++;
if(y<=n){
cout<<"? "<<4<<" "<<p1<<" "<<p2<<" "<<x<<" "<<y<<endl;
ll ax,ay;
cin>>ax>>ay;
if(ax==n/2||ay==n/2)p3=x,p4=y;
if(ax==n/2+1||ay==n/2+1)p5=x,p6=y;
}
x=y;
}
ll ax,ay;
cout<<"? "<<4<<" "<<p1<<" "<<p2<<" "<<p3<<" "<<p4<<endl;
cin>>ax>>ay;
if(ax==n/2&&ay==n/2+1){
cout<<"! "<<p3<<" "<<p4<<endl;
return;
}
cout<<"? "<<4<<" "<<p1<<" "<<p2<<" "<<p3<<" "<<p5<<endl;
cin>>ax>>ay;
if(ax==n/2&&ay==n/2+1){
cout<<"! "<<p3<<" "<<p5<<endl;
return;
}
cout<<"? "<<4<<" "<<p1<<" "<<p2<<" "<<p3<<" "<<p6<<endl;
cin>>ax>>ay;
if(ax==n/2&&ay==n/2+1){
cout<<"! "<<p3<<" "<<p6<<endl;
return;
}
cout<<"? "<<4<<" "<<p1<<" "<<p2<<" "<<p4<<" "<<p5<<endl;
cin>>ax>>ay;
if(ax==n/2&&ay==n/2+1){
cout<<"! "<<p4<<" "<<p5<<endl;
return;
}
cout<<"? "<<4<<" "<<p1<<" "<<p2<<" "<<p4<<" "<<p6<<endl;
cin>>ax>>ay;
if(ax==n/2&&ay==n/2+1){
cout<<"! "<<p4<<" "<<p6<<endl;
return;
}
cout<<"? "<<4<<" "<<p1<<" "<<p2<<" "<<p5<<" "<<p6<<endl;
cin>>ax>>ay;
if(ax==n/2&&ay==n/2+1){
cout<<"! "<<p5<<" "<<p6<<endl;
return;
}
}
int main(){
int T;
cin>>T;
while(T--)sol();
}