题目链接:https://codeforces.com/contest/1521/problem/C
This is an interactive problem!
Nastia has a hidden permutation p of length n consisting of integers from 1 to n. You, for some reason, want to figure out the permutation. To do that, you can give her an integer t (1≤t≤2), two different indices i and j (1≤i,j≤n, i≠j), and an integer x (1≤x≤n−1).
Depending on t, she will answer:
t=1: max(min(x,pi),min(x+1,pj));
t=2: min(max(x,pi),max(x+1,pj)).
You can ask Nastia at most ⌊3⋅n2⌋+30 times. It is guaranteed that she will not change her permutation depending on your queries. Can you guess the permutation?
Input
The input consists of several test cases. In the beginning, you receive the integer T (1≤T≤10000) — the number of test cases.
At the beginning of each test case, you receive an integer n (3≤n≤104) — the length of the permutation p.
It’s guaranteed that the permutation is fixed beforehand and that the sum of n in one test doesn’t exceed 2⋅104.
Interaction
To ask a question, print “? t i j x” (t=1 or t=2, 1≤i,j≤n, i≠j, 1≤x≤n−1) Then, you should read the answer.
If we answer with −1 instead of a valid answer, that means you exceeded the number of queries or made an invalid query. Exit immediately after receiving −1 and you will see the Wrong Answer verdict. Otherwise, you can get an arbitrary verdict because your solution will continue to read from a closed stream.
To print the answer, print "! p1 p2 … pn (without quotes). Note that answering doesn’t count as one of the ⌊3⋅n2⌋+30 queries.
分析
只需要通过一个式子找到 1 或者 n 的位置,然后再通过另一个式子就能每次查询得出每个位置上的数。
比如我们先通过第一个式子来找:? i (i+1) (n-1),如果得到 n ,那么 n 的位置肯定在 i+1 位置上,如果得到 n-1 那么我们再找 ? (i+1) i (n-1) ,如果是 n ,那么 n 的位置一定在 i 上。
得到 n 的位置后,我们通过第二个式子即可得出每个位置的数。
这个方法最坏的情况要查询 3 * n / 2 多一点点,符合要求。
代码
#include <bits/stdc++.h>
using namespace std;
int ans[10005];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
int in=n;
for(int i=1;i<n;i+=2)
{
cout<<"? 1 "<<i<<" "<<i+1<<" "<<n-1<<endl;
int temp;
cin>>temp;
if(temp==n)
{
in=i+1;
break;
}
else if(temp==(n-1))
{
cout<<"? 1 "<<i+1<<" "<<i<<" "<<n-1<<endl;
cin>>temp;
if(temp==n)
{
in=i;
break;
}
}
}
ans[in]=n;
for(int i=1;i<=n;i++)
{
if(i==in)
continue;
cout<<"? 2 "<<i<<" "<<in<<" 1"<<endl;
int temp;
cin>>temp;
ans[i]=temp;
}
cout<<"! ";
for (int i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
cout<<endl;
}
}