#include #include #include #include #include using namespace std; const long long INF = 1000000000000000001LL; // 10^18 + 1 to prevent overflow // Saturated addition long long add(long long a, long long b) { return min(INF, a + b); } // Saturated multiplication long long mul(long long a, long long b) { if (a == 0 || b == 0) return 0; if (INF / a < b) return INF; return min(INF, a * b); } // 0: P, 1: R, 2: S // P beats R, R beats S, S beats P int lose(int c) { return (c + 1) % 3; } int N; long long K; vector A; vector left_child, right_child, parent; vector> dp; // Fenwick tree to track active elements and simulate the exact tree merges struct Fenwick { int n; vector tree; Fenwick(int n) : n(n), tree(n + 1, 0) {} void add(int i, int delta) { for (; i <= n; i += i & -i) tree[i] += delta; } int find_kth(int k) { int idx = 0; for (int i = 1 << 18; i > 0; i >>= 1) { // 2^18 > 200000 if (idx + i <= n && tree[idx + i] < k) { idx += i; k -= tree[idx]; } } return idx + 1; } }; // Re-evaluates a single node based on its children void update_node(int u) { int L = left_child[u]; int R = right_child[u]; for (int c = 0; c < 3; ++c) { int lc = lose(c); dp[u][c] = add(mul(dp[L][c], dp[R][lc]), mul(dp[L][lc], dp[R][c])); } } // Propagates state upwards until a node's state no longer changes void propagate(int u) { while (parent[u] != 0) { u = parent[u]; array old_dp = dp[u]; update_node(u); // Critical optimization: break early if combinations saturate/stabilize if (dp[u] == old_dp) break; } } void solve() { cin >> N >> K; A.resize(N); for (int i = 1; i < N; i++) cin >> A[i]; left_child.assign(2 * N, 0); right_child.assign(2 * N, 0); parent.assign(2 * N, 0); dp.assign(2 * N, {0, 0, 0}); Fenwick fenw(N); vector node_at(N + 1); for (int i = 1; i <= N; i++) { fenw.add(i, 1); node_at[i] = i; } // Phase 1: Build the evaluation tree structure for (int i = 1; i < N; i++) { int pos1 = fenw.find_kth(A[i]); int pos2 = fenw.find_kth(A[i] + 1); int u = node_at[pos1]; int v = node_at[pos2]; int idx = N + i; left_child[idx] = u; right_child[idx] = v; parent[u] = idx; parent[v] = idx; node_at[pos1] = idx; fenw.add(pos2, -1); } int root = 2 * N - 1; // Process targets in the exact output order requested: R, P, S // Mapped as: R = 1, P = 0, S = 2 int target_order[3] = {1, 0, 2}; for (int target : target_order) { // Reset the evaluation tree assuming all leaves are completely unrestricted for (int i = 1; i <= N; i++) dp[i] = {1, 1, 1}; for (int i = N + 1; i <= 2 * N - 1; i++) update_node(i); // Quick check if the target string is even possible if (dp[root][target] < K) { cout << "-1\n"; continue; } long long current_k = K; string ans = ""; // Phase 2: Traverse leaf by leaf to determine the K-th lexicographical string for (int i = 1; i <= N; i++) { // Lexicographical alphabetical testing: 'P', then 'R', then 'S' for (int c = 0; c < 3; ++c) { // Apply a tentative character constraint and bubble up dp[i] = {0, 0, 0}; dp[i][c] = 1; propagate(i); if (dp[root][target] >= current_k) { // This character branch contains our K-th target string, so we lock it if (c == 0) ans += 'P'; else if (c == 1) ans += 'R'; else ans += 'S'; break; } else { // Not in this branch, decrease the K target and test the next character current_k -= dp[root][target]; } } } cout << ans << "\n"; } } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int t; if (cin >> t) { while (t--) { solve(); } } return 0; }