https://codeforces.com/contest/1270/problem/D
思路:
n>=k,答案可能与k有关
参考:
https://blog.csdn.net/qq_41997978/article/details/103769455
因为数组两两不相同,第一次先询问 1 ,…,k,得到第一组答案,设返回的是 a[x]。接下来每次用 k + 1依次换掉1,…,k。设当前换掉的是 i,若返回的答案和第一组相同,说明a[k + 1] 和 a[i] 在 a[x]的同一边,否则 a[i] 在 a[k + 1]的对立边。
如何确定a[k + 1] 在 a[x]哪一边:若返回的答案和第一组不相同,有两种情况:一是 你用一个比a[x] 大的数换掉一个比a[x]小的数,这种情况返回的答案一定偏大,即a[k + 1] > a[x]。 另外一种情况则是 a[k + 1] < a[x]。
因为你一定会换掉a[x],这种情况至少发生一次,可以得知两个信息:a[k + 1] 和 a[x]的相对大小,和a[k + 1]在同一边的数字的个数。依靠这两个信息就可以求出 m。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=510;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL a[maxn];
int main(void){
LL n,k;cin>>n>>k;
if(k==1){
cout<<"! "<<1<<endl;
return 0;
}
cout<<"? ";
for(LL i=1;i<=k;i++){
cout<<i<<" ";
}
cout<<endl;
LL posx,numx;
cin>>posx>>numx;
a[posx]=numx;
LL sum=0;
bool flag=0;///如果a[k+1]比a[x]大,flag=1;
for(LL j=1;j<=k;j++){
cout<<"? ";
for(LL p=1;p<=k+1;p++){
if(p==j) continue;
cout<<p<<" ";
}
cout<<endl;
LL pos,num;
cin>>pos>>num;
a[pos]=num;
if(pos==posx){
sum++;
}
else{
if(num>a[posx]){
flag=1;
}
}
}
if(flag){
cout<<"! "<<k-sum<<endl;
}
else{
cout<<"! "<<sum+1<<endl;
}
return 0;
}