#pragma GCC optimize("O3,unroll-loops") #include #include #include #include using namespace std; const long long INF = 1000000000000000001LL; inline long long add(long long a, long long b) { return min(INF, a + b); } inline 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); } // 3x3 Matrix for Dynamic DP struct Mat { long long m[3][3]; Mat() { for(int i=0; i<3; ++i) for(int j=0; j<3; ++j) m[i][j] = 0; } Mat operator*(const Mat& other) const { Mat res; for(int i=0; i<3; ++i) { for(int k=0; k<3; ++k) { if (m[i][k] == 0) continue; for(int j=0; j<3; ++j) { res.m[i][j] = add(res.m[i][j], mul(m[i][k], other.m[k][j])); } } } return res; } }; // Coefficient matrix for an internal node Mat get_matrix(long long v[3]) { Mat res; res.m[0][0] = v[1]; res.m[0][1] = v[0]; res.m[0][2] = 0; res.m[1][0] = 0; res.m[1][1] = v[2]; res.m[1][2] = v[1]; res.m[2][0] = v[2]; res.m[2][1] = 0; res.m[2][2] = v[0]; return res; } // Matrix representation of a leaf vector Mat get_leaf_matrix(long long v[3]) { Mat res; res.m[0][0] = v[0]; res.m[1][0] = v[1]; res.m[2][0] = v[2]; return res; } const int MAXN = 200005; int N; long long K; int left_child[MAXN * 2], right_child[MAXN * 2], parent_node[MAXN * 2]; int sz[MAXN * 2], heavy[MAXN * 2], light[MAXN * 2]; int top_node[MAXN * 2], in[MAXN * 2], pos_to_node[MAXN * 2]; int end_of_heavy[MAXN * 2]; int timer_hld; long long V[MAXN * 2][3]; Mat tree_seg[MAXN * 8]; // Fenwick tree to track active elements during 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) { if (idx + i <= n && tree[idx + i] < k) { idx += i; k -= tree[idx]; } } return idx + 1; } }; void dfs_sz(int u) { sz[u] = 1; heavy[u] = light[u] = 0; if (u <= N) return; dfs_sz(left_child[u]); dfs_sz(right_child[u]); sz[u] += sz[left_child[u]] + sz[right_child[u]]; if (sz[left_child[u]] > sz[right_child[u]]) { heavy[u] = left_child[u]; light[u] = right_child[u]; } else { heavy[u] = right_child[u]; light[u] = left_child[u]; } } void dfs_hld(int u, int t) { top_node[u] = t; in[u] = ++timer_hld; pos_to_node[timer_hld] = u; if (u <= N) { end_of_heavy[t] = u; return; } dfs_hld(heavy[u], t); dfs_hld(light[u], light[u]); } void dfs_init_V(int u) { if (u <= N) { V[u][0] = V[u][1] = V[u][2] = 1; return; } int L = left_child[u], R = right_child[u]; dfs_init_V(L); dfs_init_V(R); V[u][0] = add(mul(V[L][0], V[R][1]), mul(V[L][1], V[R][0])); V[u][1] = add(mul(V[L][1], V[R][2]), mul(V[L][2], V[R][1])); V[u][2] = add(mul(V[L][2], V[R][0]), mul(V[L][0], V[R][2])); } void build_seg(int node, int L, int R) { if (L == R) { int u = pos_to_node[L]; if (u <= N) tree_seg[node] = get_leaf_matrix(V[u]); else tree_seg[node] = get_matrix(V[light[u]]); return; } int mid = (L + R) / 2; build_seg(node * 2, L, mid); build_seg(node * 2 + 1, mid + 1, R); tree_seg[node] = tree_seg[node * 2] * tree_seg[node * 2 + 1]; } void update_seg(int node, int L, int R, int pos, const Mat& val) { if (L == R) { tree_seg[node] = val; return; } int mid = (L + R) / 2; if (pos <= mid) update_seg(node * 2, L, mid, pos, val); else update_seg(node * 2 + 1, mid + 1, R, pos, val); tree_seg[node] = tree_seg[node * 2] * tree_seg[node * 2 + 1]; } Mat query_seg(int node, int L, int R, int qL, int qR) { if (qL <= L && R <= qR) return tree_seg[node]; int mid = (L + R) / 2; if (qR <= mid) return query_seg(node * 2, L, mid, qL, qR); if (qL > mid) return query_seg(node * 2 + 1, mid + 1, R, qL, qR); return query_seg(node * 2, L, mid, qL, qR) * query_seg(node * 2 + 1, mid + 1, R, qL, qR); } void update_leaf(int leaf, long long new_V[3]) { V[leaf][0] = new_V[0]; V[leaf][1] = new_V[1]; V[leaf][2] = new_V[2]; update_seg(1, 1, timer_hld, in[leaf], get_leaf_matrix(V[leaf])); int u = leaf; while (u != 0) { int t = top_node[u]; Mat res = query_seg(1, 1, timer_hld, in[t], in[end_of_heavy[t]]); V[t][0] = res.m[0][0]; V[t][1] = res.m[1][0]; V[t][2] = res.m[2][0]; int p = parent_node[t]; if (p != 0) update_seg(1, 1, timer_hld, in[p], get_matrix(V[t])); u = p; } } void solve() { cin >> N >> K; vector A(N); for (int i = 1; i < N; i++) cin >> A[i]; long long max_k = 1; bool k_valid = false; for (int i = 1; i < N; i++) { max_k *= 2; if (max_k >= K) { k_valid = true; break; } } if (!k_valid) { cout << "-1\n-1\n-1\n"; return; } Fenwick fenw(N); vector node_at(N + 1); for (int i = 1; i <= N; i++) { fenw.add(i, 1); node_at[i] = i; } for (int i = 1; i < N; i++) { int p1 = fenw.find_kth(A[i]), p2 = fenw.find_kth(A[i] + 1); int u = node_at[p1], v = node_at[p2]; int idx = N + i; left_child[idx] = u; right_child[idx] = v; parent_node[u] = parent_node[v] = idx; node_at[p1] = idx; fenw.add(p2, -1); } int root = 2 * N - 1; parent_node[root] = 0; timer_hld = 0; dfs_sz(root); dfs_hld(root, root); dfs_init_V(root); build_seg(1, 1, timer_hld); // Fast copy system state vector backup_tree(tree_seg + 1, tree_seg + 1 + 4 * timer_hld); long long backup_V[MAXN * 2][3]; for (int i = 1; i <= 2 * N - 1; i++) for (int j = 0; j < 3; j++) backup_V[i][j] = V[i][j]; int target_order[3] = {1, 0, 2}; // R, P, S for (int i = 0; i < 3; i++) { if (i > 0) { for (int j = 1; j <= 4 * timer_hld; j++) tree_seg[j] = backup_tree[j - 1]; for (int j = 1; j <= 2 * N - 1; j++) for (int k = 0; k < 3; k++) V[j][k] = backup_V[j][k]; } int target = target_order[i]; if (V[root][target] < K) { cout << "-1\n"; continue; } long long current_k = K; string ans = ""; for (int j = 1; j <= N; j++) { for (int c = 0; c < 3; ++c) { long long newV[3] = {0, 0, 0}; newV[c] = 1; update_leaf(j, newV); if (V[root][target] >= current_k) { ans += (c == 0 ? 'P' : (c == 1 ? 'R' : 'S')); break; } else { current_k -= V[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; }