#include using namespace std; using ull = unsigned long long; static const ull INF = (ull)4e18; static inline ull cap_add(ull a, ull b) { ull c = a + b; if (c < a || c > INF) return INF; return c; } static inline ull cap_mul(ull a, ull b) { __uint128_t z = (__uint128_t)a * (__uint128_t)b; if (z > INF) return INF; return (ull)z; } // 0:R, 1:P, 2:S static inline int loseTo(int x) { // winner x beats loseTo(x) if (x == 0) return 2; // R beats S if (x == 1) return 0; // P beats R return 1; // S beats P } static inline int winner(int a, int b) { if (a == b) return -1; // invalid return (loseTo(a) == b ? a : b); } struct Fenwick { int n; vector bit; Fenwick() {} Fenwick(int n): n(n), bit(n + 1, 0) {} void add(int i, int v) { for (; i <= n; i += i & -i) bit[i] += v; } int kth(int k) const { int idx = 0; int pw = 1; while ((pw << 1) <= n) pw <<= 1; for (int d = pw; d; d >>= 1) { int ni = idx + d; if (ni <= n && bit[ni] < k) { idx = ni; k -= bit[ni]; } } return idx + 1; } }; struct Node { int l = -1, r = -1; int L = -1, R = -1; // leaf interval array dp{0, 0, 0}; }; static inline array pull(const array& A, const array& B) { array res{0, 0, 0}; for (int t = 0; t < 3; t++) { int z = loseTo(t); res[t] = cap_add( cap_mul(A[t], B[z]), cap_mul(A[z], B[t]) ); } return res; } // weighted total = sum_r w[r] * dp[u][r] static inline ull weighted_total(const array& w, const array& dp) { ull ret = 0; for (int i = 0; i < 3; i++) ret = cap_add(ret, cap_mul(w[i], dp[i])); return ret; } // left subtree context weights // cL[a] = number of completions (right subtree + outside) if left outcome is a static inline array left_ctx(const array& w, const array& dpR) { array c{0, 0, 0}; for (int t = 0; t < 3; t++) { int z = loseTo(t); // left outcome = t, right outcome = z -> parent t c[t] = cap_add(c[t], cap_mul(w[t], dpR[z])); // left outcome = z, right outcome = t -> parent t c[z] = cap_add(c[z], cap_mul(w[t], dpR[t])); } return c; } // right subtree context weights if left outcome is fixed to a // dR[b] = number of completions (outside) if right outcome is b static inline array right_ctx(const array& w, int a) { array d{0, 0, 0}; for (int t = 0; t < 3; t++) { int z = loseTo(t); if (a == t) { // need right = z d[z] = cap_add(d[z], w[t]); } if (a == z) { // need right = t d[t] = cap_add(d[t], w[t]); } } return d; } struct Frame { int u; array w; ull K; int stage; // 0: enter, 1: after left, 2: after right int leftOutcome; ull leftResidual; }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int N; ull K; cin >> N >> K; vector A(N); for (int i = 1; i <= N - 1; i++) cin >> A[i]; vector tr(2 * N + 5); for (int i = 1; i <= N; i++) { tr[i].L = tr[i].R = i; tr[i].dp = {1, 1, 1}; // leaf can be R/P/S } // Build merge tree from A vector rootAtPos(N + 1); for (int i = 1; i <= N; i++) rootAtPos[i] = i; Fenwick fw(N); for (int i = 1; i <= N; i++) fw.add(i, 1); int ptr = N; for (int i = 1; i <= N - 1; i++) { int k = A[i]; int posL = fw.kth(k); int posR = fw.kth(k + 1); int x = rootAtPos[posL]; int y = rootAtPos[posR]; ++ptr; tr[ptr].l = x; tr[ptr].r = y; tr[ptr].L = tr[x].L; tr[ptr].R = tr[y].R; tr[ptr].dp = pull(tr[x].dp, tr[y].dp); rootAtPos[posL] = ptr; fw.add(posR, -1); } int onlyPos = fw.kth(1); int root = rootAtPos[onlyPos]; auto solve_for_target = [&](int target) -> string { array rootW{0, 0, 0}; rootW[target] = 1; if (weighted_total(rootW, tr[root].dp) < K) return "-1"; vector ans(N + 1, '?'); vector st; st.reserve(2 * N + 5); st.push_back({root, rootW, K, 0, -1, 0}); int retOutcome = -1; ull retResidual = 0; static const int order[3] = {1, 0, 2}; // P < R < S static const char chOf[3] = {'R', 'P', 'S'}; while (!st.empty()) { Frame &f = st.back(); int u = f.u; if (f.stage == 0) { ull total = weighted_total(f.w, tr[u].dp); if (total < f.K) { return "-1"; } if (tr[u].l == -1) { // leaf ull kcur = f.K; bool ok = false; for (int idx = 0; idx < 3; idx++) { int c = order[idx]; ull cnt = f.w[c]; if (kcur > cnt) { kcur -= cnt; } else { ans[tr[u].L] = chOf[c]; retOutcome = c; retResidual = kcur; // rank inside this leaf choice block ok = true; break; } } if (!ok) return "-1"; st.pop_back(); continue; } // go left first array cL = left_ctx(f.w, tr[tr[u].r].dp); f.stage = 1; st.push_back({tr[u].l, cL, f.K, 0, -1, 0}); continue; } if (f.stage == 1) { // left child returned f.leftOutcome = retOutcome; f.leftResidual = retResidual; array dR = right_ctx(f.w, f.leftOutcome); f.stage = 2; st.push_back({tr[u].r, dR, f.leftResidual, 0, -1, 0}); continue; } // stage == 2 { int rightOutcome = retOutcome; ull rightResidual = retResidual; int w = winner(f.leftOutcome, rightOutcome); if (w == -1) return "-1"; retOutcome = w; retResidual = rightResidual; st.pop_back(); } } string res; res.reserve(N); for (int i = 1; i <= N; i++) res.push_back(ans[i]); return res; }; cout << solve_for_target(0) << '\n'; // R cout << solve_for_target(1) << '\n'; // P cout << solve_for_target(2) << '\n'; // S } return 0; }