#include using namespace std; using ll=long long; const ll ILL=2167167167167167167; const int INF=2100000000; #define rep(i,a,b) for (int i=(int)(a);i<(int)(b);i++) #define all(p) p.begin(),p.end() template using pq_ = priority_queue, greater>; template int LB(vector &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();} template int UB(vector &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();} template bool chmin(T &a,T b){if(b bool chmax(T &a,T b){if(a void So(vector &v) {sort(v.begin(),v.end());} template void Sore(vector &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});} bool yneos(bool a,bool upp=false){if(a){cout<<(upp?"YES\n":"Yes\n");}else{cout<<(upp?"NO\n":"No\n");}return a;} template void vec_out(vector &p,int ty=0){ if(ty==2){cout<<'{';for(int i=0;i<(int)p.size();i++){if(i){cout<<",";}cout<<'"'< T vec_min(vector &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;} template T vec_max(vector &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;} template T vec_sum(vector &a){T ans=T(0);for(auto &x:a) ans+=x;return ans;} int pop_count(long long a){int res=0;while(a){res+=(int)(a&1),a>>=1;}return res;} template T square(T a){return a * a;} #include int op(int a, int b) { return a + b; } int e() { return 0; } int target; bool f(int x) { return x <= target; } void solve(); // DEAR MYSTERIES / TOMOO int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t = 1; cin >> t; rep(i, 0, t) solve(); } void solve(){ int N; ll K; cin >> N >> K; vector A(N - 1); rep(i, 0, N - 1) cin >> A[i], A[i]--; if (N <= 60 && K > (1ll << (N - 1))) { rep(rp, 0, 3) { cout << "-1\n"; } return; } // vector pare(N * 2 - 1, -1); vector L(N - 1), R(N - 1); vector w(N * 2 - 1); vector p2(N, 1); rep(i, 0, N - 1) p2[i + 1] = min(ILL, p2[i] * 2); { vector tmp(N); rep(i, 0, N) tmp[i] = N - 1 + i; atcoder::segtree seg(vector(N, 1)); rep(i, 0, N - 1) { target = A[i]; int l = seg.max_right(0); target++; int r = seg.max_right(0); seg.set(r, 0); // pare[tmp[l]] = N - 2 - i; // pare[tmp[r]] = N - 2 - i; L[N - 2 - i] = tmp[l]; R[N - 2 - i] = tmp[r]; w[N - 2 - i] = w[tmp[l]] + w[tmp[r]] + 1; tmp[l] = N - 2 - i; } } string hand = "PRS"; for (int root : {1, 0, 2}) { ll rem = K - 1; auto dfs = [&](auto self, int x, int wei, vector dp) -> int { if (x >= N - 1) { rep(j, 0, 3) { // rem < dp[x][j] * p2[wei] // rem / (double)p2[wei] < dp[x][j] // rem / p2[wei] < dp[x][j] if (rem / p2[wei] < dp[j]) { cout << hand[j]; return j; } rem -= dp[j] * p2[wei]; } assert(false); } vector n_dp(3); rep(j, 0, 3) { n_dp[j] += dp[j]; n_dp[(j + 1) % 3] += dp[j]; } rep(j, 0, 3) chmin(n_dp[j], ILL); int a = self(self, L[x], wei + w[R[x]], n_dp); // L[x] が a -> 親は a or a - 1 // a -> a + 1, a - 1 -> a - 1 rep(j, 0, 3) n_dp[j] = 0; n_dp[(a + 1) % 3] = dp[a]; n_dp[(a + 2) % 3] = dp[(a + 2) % 3]; int b = self(self, R[x], wei, n_dp); if (a > b) swap(a, b); if (b - a == 1) return a; return 2; }; vector init(3); init[root] = 1; dfs(dfs, 0, 0, init); cout << "\n"; } } /* * 操作に対応した 2 ぶんき * を考える * N - 1 個の頂点について、辺をいずれか選ぶ * このとき、S[i] は頂点 i から根の間であって、 * 選ばれた辺の数と対応する * 左側で RP のうち、文字列最小のものは? * という問題を解く * 適切に変換を加えれば、 * P -> 0, R -> 1, S -> 2 * とする * すると、min(a, b) が上に書き込まれるということになる ((min(0, 2) = 2) * c = (a + b - 1) * 2 * 単純に dp でいいんじゃないかな? * それをするには、sum depth かかってしまう * 最悪計算量が O(N^2) * それを HLD で高速化する * ある頂点には、 * min 側のやつと、 * 普通に行列を持つと 27 倍の定数倍がついた O(N log^2) なので終わり * 行列の形が * * ある頂点の値を決めたい * その頂点が左がわであるとき、 * 右側はどの値でも 2^leaf 通り * 左側は確定している * * DFS でいい? * * 辞書順貪欲と、DFS 行き順が噛み合ってていいね * */