#include using namespace std; using ll = long long; using ld = long double; using ull = unsigned long long; #define rep(i,n) for(ll i=0;i T div_floor(T a, T b) { return a / b - ((a ^ b) < 0 && a % b); } template T div_ceil(T a, T b) { return a / b + ((a ^ b) > 0 && a % b); } template inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; } template inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; } template ostream &operator<<(ostream &os, const vector &a){ if (a.empty()) return os; os << a.front(); for (auto e : a | views::drop(1)){ os << ' ' << e; } return os; } void dump(auto ...vs){ ((cout << vs << ' '), ...) << endl; } bool local=false; vector ansP; void solve() { ll N; cin>>N; if (local){ ansP=vector(N,-1); rep(i,N){ cin>>ansP[i]; } } ll query_num=0; auto query=[&](ll i,ll j){ assert (i!=j); query_num++; assert(query_num<3*N); cout<<"1 "<>k; } k--; if (k<0)k++; return k; }; auto answer=[&](vector P){ cout<<2; rep(i,N){ cout<<' '; cout<=0){ base_i=i; break; } } if (base_i==-1){ ll r=query(N-1,0); if (r>=0){ base_i=N-1; } } assert(base_i>=0); vector nxt(N,-1); rep(j,N){ if (j==base_i)continue; nxt[j]=query(base_i,j); } vector is_start(N,true); rep(i,N){ if (nxt[i]>=0){ is_start[nxt[i]]=false; } } vector> com; rep(i,N){ if (i==base_i)continue; if (is_start[i]){ vector c; ll ni=i; while (ni>=0){ c.push_back(ni); ni=nxt[ni]; } com.push_back(c); } } sort(all(com),[](vector a,vector b){ return a.size()>b.size(); }); if (com.size()>=2){ if (com[com.size()-1].size()==com[com.size()-2].size()){ com.push_back({}); } } reverse(all(com.back())); com.back().push_back(base_i); reverse(all(com.back())); // for (auto i:com){ // dump(i); // } auto divide_com=[&](vector> &C){ ll B=C.size(); vector D(N); rep(i,B){ for (ll j:C[i]){ D[j]=i; } } ll v=0; vector nxt(B,-1); vector over(B,false); rep(i,B){ if (i==0){ continue; } else{ ll r=query(C[i][0],C[0][0]); if (r!=C[D[r]][0]){ over[i]=true; v++; } nxt[i]=D[r]; } } vector start_nxt(N,true); rep(i,B){ if (nxt[i]>=0){ start_nxt[nxt[i]]=false; } } rep(i,B){ if (start_nxt[i]){ nxt[0]=i; if (C[i].size()>1){ ll r=query(C[0][0],C[0][1]); if (r==-1 or r!=C[D[r]][1]){ over[0]=true; v++; } } break; } } vector used(B,false); vector> nc; rep(i,B){ if (used[i])continue; ll ni=i; ll now=0; vector> a; while (true){ used[ni]=true; a.emplace_back(ni,now); now+=v; if (over[ni]){ now-=B; } ni=nxt[ni]; if (used[ni])break; } vector> L; ll idx=0; while (true){ bool flag=false; for (auto [ai,av]:a){ if (idx ncc; for (auto [v,i]:L){ ncc.push_back(i); } nc.push_back(ncc); } sort(all(nc),[](vector a,vector b){ return a.size()>b.size(); }); swap(C,nc); return; }; while (com.size()>=2){ divide_com(com); // for (auto i:com){ // dump(i); // } } assert (com[0].size()==N); vector P(N); rep(i,N){ P[com[0][i]]=i+1; } answer(P); return; } int main() { cin.tie(0)->sync_with_stdio(0); ll T=1; cin>>T; while (T--){ solve(); } return 0; }