题解 CF1521C 【Nastia and a Hidden Permutation】
CF救命题,没这题就rk 5k了...
不难发现,若我们已经掌握 1 i j n-1 来得到
于是我们用
考虑这样一条询问的意义:2 j k 1
根据题意,它表示的是
-
返回值为
1 ,即\min(p_j,max(2,p_k))=1 ,其中max(2,p_k)\geq2 ,故p_j=1 。 -
返回值为
2 ,即\min(p_j,max(2,p_k))=2 ,则p_j=2 或p_k\leq2 。 -
返回值
>2 ,即\min(p_j,max(2,p_k))>2 ,则p_j>2 且p_k>2 。
分别观察一下:第一种给了我们需要的 2 k j 1 确定
先假设 2 k k+1 1,则我们会共执行
于是我们通过
代码:
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define SZ(k) k.size()
#define ALL(k) k.begin(),k.end()
#define DEBUG(k...) fprintf(stderr,k)
#define pb push_back
#define fi first
#define se second
typedef long long ll;
typedef pair<int,int> pii;
template<class T>inline bool chkmax(T &x,const T &y){return x<y?x=y,true:false;}
template<class T>inline bool chkmin(T &x,const T &y){return x>y?x=y,true:false;}
const int maxn=2e5+10;
int ans[maxn],n,rt,t_case;
inline void ask(int op,int i,int j,int x){
cout<<"? "<<op<<" "<<i<<" "<<j<<" "<<x<<endl;
}
int main(){
cin>>t_case;
while(t_case--){
cin>>n;
rt=0;
for(ri i=1,j;i<n;i+=2){
ask(2,i,i+1,1);
cin>>j;
if(j==1){rt=i;break;}
if(j==2){
ask(2,i+1,1,1);
cin>>j;
if(j==1){rt=i+1;break;}
}
}
if(!rt)rt=n;
ans[rt]=1;
for(ri i=1;i<=n;++i)
if(i!=rt){
ask(1,rt,i,n-1);
cin>>ans[i];
}
cout<<"!";
for(ri i=1;i<=n;++i)cout<<" "<<ans[i];
cout<<endl;
}
return 0;
}