#include using namespace std; struct Weighted_dsu { public: Weighted_dsu() : _n(0) {} Weighted_dsu(int n) : _n(n), num_component(n), parent_or_size(n, -1), diff_weight(n) {} bool merge(int a, int b, long long w) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); int x = leader(a), y = leader(b); w += diff_weight[a] - diff_weight[b]; if(x == y) return w == 0; if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y), w *= -1; parent_or_size[x] += parent_or_size[y]; parent_or_size[y] = x; diff_weight[y] = w; num_component--; return true; } long long diff(int a, int b) { assert(same(a, b)); return diff_weight[b] - diff_weight[a]; } bool same(int a, int b) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); return leader(a) == leader(b); } int leader(int a) { assert(0 <= a && a < _n); if (parent_or_size[a] < 0) return a; int r = leader(parent_or_size[a]); diff_weight[a] += diff_weight[parent_or_size[a]]; return parent_or_size[a] = r; } int size() { return num_component; } int size(int a) { assert(0 <= a && a < _n); return -parent_or_size[leader(a)]; } std::vector> groups() { std::vector leader_buf(_n), group_size(_n); for (int i = 0; i < _n; i++) { leader_buf[i] = leader(i); group_size[leader_buf[i]]++; } std::vector> result(_n); for (int i = 0; i < _n; i++) { result[i].reserve(group_size[i]); } for (int i = 0; i < _n; i++) { result[leader_buf[i]].push_back(i); } result.erase( std::remove_if(result.begin(), result.end(), [&](const std::vector& v) { return v.empty(); }), result.end()); return result; } int _n, num_component; std::vector parent_or_size; std::vector diff_weight; }; //#define DBG #ifndef DBG int ask(int u, int v){ int res; cout << "1 " << u + 1 << ' ' << v + 1 << endl; cin >> res; if(res == -1) return -1; res--; return res; } #else vector a = {2, 3, 4, 1, 5}; int ask(int u, int v){ int res; cout << "1 " << u + 1 << ' ' << v + 1 << endl; int vl = a[u] + a[v]; for(int i = 0; i < a.size(); i++){ if(a[i] == vl) return i; } return -1; } #endif void solve(){ int n; #ifndef DBG cin >> n; #else n = a.size(); #endif auto check = [&](vector ans){ int n = ans.size(); vector used(n + 1); for(int i = 0; i < n; i++){ if(ans[i] > n) return false; if(used[ans[i]]) return false; used[ans[i]] = true; } return true; }; vector>> T; vector cand(n, -1); Weighted_dsu uf(n); vector used(n, true); auto f = [&](int p){ int cnt = 0; vector es(n); vector> T2; used[p] = false; for(int i = 0; i < n; i++){ if(i == p) continue; int u = ask(p, i); T2.emplace_back(p, i, u); if(u == -1){ cnt++; }else{ es[i] = true; } } for(auto [p, u, v] : T2){ es[v] = false; } for(int i = 0; i < n; i++){ if(!used[i]) continue; if(!es[i]) used[i] = false; } T.emplace_back(T2); }; for(int i = 0; i < 3; i++){ int p = -1; for(int j = 0; j < n; j++){ if(used[j]){ p = j; break; } } if(p != -1){ f(p); } } auto dfs = [&](auto dfs, int turn, Weighted_dsu uf) -> bool { if(turn == T.size()){ int mn = 0; vector ans(n); for(int v = 0; v < n; v++){ ans[v] = uf.diff(0, v); mn = min(mn, ans[v]); } for(int v = 0; v < n; v++){ ans[v] -= mn - 1; } if(check(ans)){ cout << "2"; for(int i = 0; i < n; i++) cout << ' ' << ans[i]; cout << endl; return true; }else{ return false; } } int pos = get<0>(T[turn][0]); int cnt0 = 0, cnt1 = 0; for(auto [p, u, v] : T[turn]){ if(v == -1) cnt1++; else cnt0++; } if(cnt1 == cnt0){ { auto uf2 = uf; cand[pos] = cnt1; for(auto [p, u, v] : T[turn]){ if(v == -1) continue; uf2.merge(u, v, cnt1); if(cand[u] != -1) uf2.merge(p, v, cand[u]); } if(dfs(dfs, turn + 1, uf2)) return true; } { auto uf2 = uf; cand[pos] = cnt1 + 1; for(auto [p, u, v] : T[turn]){ if(v == -1) continue; uf2.merge(u, v, cnt1 + 1); if(cand[u] != -1) uf2.merge(p, v, cand[u]); } if(dfs(dfs, turn + 1, uf2)) return true; } cand[pos] = -1; }else{ if(cnt1 > cnt0) cnt1++; cand[pos] = cnt1; for(auto [p, u, v] : T[turn]){ if(v == -1) continue; uf.merge(u, v, cnt1); if(cand[u] != -1) uf.merge(p, v, cand[u]); } if(dfs(dfs, turn + 1, uf)) return true; cand[pos] = -1; } return false; }; assert(dfs(dfs, 0, uf)); } int main(){ ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; while(T--) solve(); }