// GPT 5.4-pro テスト #include using namespace std; using ull = unsigned long long; struct Fenwick { int n; vector bit; Fenwick() {} explicit Fenwick(int n): n(n), bit(n + 1, 0) {} void add(int idx, int val) { for (; idx <= n; idx += idx & -idx) bit[idx] += val; } // 1-indexed: 最小の idx で prefix sum >= k int kth(int k) const { int idx = 0; int step = 1; while ((step << 1) <= n) step <<= 1; for (int d = step; d > 0; d >>= 1) { int nxt = idx + d; if (nxt <= n && bit[nxt] < k) { idx = nxt; k -= bit[nxt]; } } return idx + 1; } }; struct Mat { ull a[3][3]{}; }; struct Solver { int N; vector A; vector L, R, SZ, curNode; int root; vector pw2; Solver(int N, vector A): N(N), A(move(A)), root(-1) { buildTree(); } // 内部表現: P=0, R=1, S=2 static char charOf(int x) { static const char table[3] = {'P', 'R', 'S'}; return table[x]; } static int lose(int x) { // x が勝つ相手 return (x + 1) % 3; } static int winner(int x, int y) { if (x == y) return -1; return (y == lose(x) ? x : y); } static ull satAdd(ull x, ull y, ull cap) { if (x >= cap || y >= cap) return cap; if (x > cap - y) return cap; return x + y; } static ull satMul(ull x, ull y, ull cap) { if (x == 0 || y == 0) return 0; __uint128_t z = (__uint128_t)x * y; if (z >= cap) return cap; return (ull)z; } static Mat identity() { Mat I; for (int i = 0; i < 3; ++i) I.a[i][i] = 1; return I; } static Mat mulMat(const Mat& A, const Mat& B, ull cap) { Mat C; for (int i = 0; i < 3; ++i) { for (int k = 0; k < 3; ++k) { if (A.a[i][k] == 0) continue; for (int j = 0; j < 3; ++j) { if (B.a[k][j] == 0) continue; C.a[i][j] = satAdd(C.a[i][j], satMul(A.a[i][k], B.a[k][j], cap), cap); } } } return C; } // v[c] = 「その部分木の結果が c になる通り数」 // y = M(v) x static Mat makeMatFromVec(const array& v) { Mat M; for (int c = 0; c < 3; ++c) { M.a[c][c] = v[lose(c)]; M.a[c][lose(c)] = v[c]; } return M; } static Mat makeMatFromFixedValue(int v) { array vec{0, 0, 0}; vec[v] = 1; return makeMatFromVec(vec); } void preparePowers(ull cap) { pw2.assign(N + 1, 1); for (int i = 1; i <= N; ++i) pw2[i] = satMul(pw2[i - 1], 2ULL, cap); } Mat makeMatFromFreeSubtree(int u) const { ull t = pw2[SZ[u] - 1]; return makeMatFromVec({t, t, t}); } optional kthStringForTarget(int target, ull K) { preparePowers(K); // 固定した 1 文字 target に対して、通り数は常に 2^(N-1) if (pw2[N - 1] < K) return nullopt; struct Frame { int u; int state; // 0: 左へ行く前, 1: 左確定済み, 2: 右確定済み Mat T; // 現在の部分木の結果ベクトル -> 根の結果ベクトル int valL; // 左部分木の確定結果 }; vector ans(N); vector st; st.reserve(2 * N); st.push_back({root, 0, identity(), -2}); bool hasRet = false; int ret = -2; ull k = K; while (!st.empty()) { Frame &f = st.back(); int u = f.u; if (L[u] == -1) { int chosen = -1; for (int ch = 0; ch < 3; ++ch) { // 辞書順 P < R < S ull cnt = f.T.a[target][ch]; if (cnt >= k) { chosen = ch; ans[u] = charOf(ch); break; } k -= cnt; } if (chosen == -1) return nullopt; ret = chosen; hasRet = true; st.pop_back(); continue; } if (f.state == 0) { f.state = 1; Mat M = makeMatFromFreeSubtree(R[u]); st.push_back({L[u], 0, mulMat(f.T, M, K), -2}); continue; } if (f.state == 1) { if (hasRet) { f.valL = ret; hasRet = false; } f.state = 2; Mat M = makeMatFromFixedValue(f.valL); st.push_back({R[u], 0, mulMat(f.T, M, K), -2}); continue; } if (hasRet) { int valR = ret; hasRet = false; ret = winner(f.valL, valR); hasRet = true; st.pop_back(); continue; } return nullopt; } return string(ans.begin(), ans.end()); } private: void buildTree() { int tot = max(1, 2 * N - 1); L.assign(tot, -1); R.assign(tot, -1); SZ.assign(tot, 1); curNode.assign(N + 1, -1); Fenwick fw(N); for (int pos = 1; pos <= N; ++pos) { fw.add(pos, 1); curNode[pos] = pos - 1; } int nxt = N; for (int ai : A) { int p = fw.kth(ai); int q = fw.kth(ai + 1); int x = curNode[p]; int y = curNode[q]; L[nxt] = x; R[nxt] = y; SZ[nxt] = SZ[x] + SZ[y]; curNode[p] = nxt; // 左側の位置にマージ結果を残す fw.add(q, -1); // 右側は消える ++nxt; } root = (N == 1 ? 0 : curNode[fw.kth(1)]); } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; ull K; cin >> N; K = 1; vector A(N - 1); for (int i = 0; i < N - 1; ++i) cin >> A[i]; Solver solver(N, A); // 出力順は R, P, S の 3 行 // 内部表現は P=0, R=1, S=2 vector targets = {1, 0, 2}; for (int target : targets) { auto ans = solver.kthStringForTarget(target, K); if (ans) cout << *ans << '\n'; else cout << -1 << '\n'; } return 0; }