結果

問題 No.3510 RPS Eliminations
コンテスト
ユーザー 👑 potato167
提出日時 2026-04-18 12:26:51
言語 C++17
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++17 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 167 ms / 2,000 ms
コード長 5,394 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 10,858 ms
コンパイル使用メモリ 223,172 KB
実行使用メモリ 58,892 KB
最終ジャッジ日時 2026-04-18 12:27:09
合計ジャッジ時間 12,964 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge2_1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 28
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <bits/stdc++.h>
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<class T> using pq_ = priority_queue<T, vector<T>, greater<T>>;
template<class T> int LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> int UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,T b){if(b<a){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,T b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &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<class T> void vec_out(vector<T> &p,int ty=0){
    if(ty==2){cout<<'{';for(int i=0;i<(int)p.size();i++){if(i){cout<<",";}cout<<'"'<<p[i]<<'"';}cout<<"}\n";}
    else{if(ty==1){cout<<p.size()<<"\n";}for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}}
template<class T> T vec_min(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;}
template<class T> T vec_max(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;}
template<class T> T vec_sum(vector<T> &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<class T> T square(T a){return a * a;}

#include<atcoder/segtree>

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<int> 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<int> pare(N * 2 - 1, -1);
    vector<int> L(N - 1), R(N - 1);
    vector<int> w(N * 2 - 1);
    vector<ll> p2(N, 1);
    rep(i, 0, N - 1) p2[i + 1] = min(ILL, p2[i] * 2);
    {
        vector<int> tmp(N);
        rep(i, 0, N) tmp[i] = N - 1 + i;
        atcoder::segtree<int, op, e> seg(vector<int>(N, 1));
        rep(i, 0, N - 1) {
            target = A[i];
            int l = seg.max_right<f>(0);
            target++;
            int r = seg.max_right<f>(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}) {
        vector dp(N * 2 - 1, vector<ll>(3));
        ll rem = K - 1;
        int var = 0;
        dp[var][root] = 1;
        auto dfs = [&](auto self, int x, int wei) -> 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[x][j]) {
                        cout << hand[j];
                        return j;
                    }
                    rem -= dp[x][j] * p2[wei];
                }
                assert(false);
            }
            rep(j, 0, 3) {
                dp[L[x]][j] += dp[x][j];
                dp[L[x]][(j + 1) % 3] += dp[x][j];
            }
            rep(j, 0, 3) chmin(dp[L[x]][j], ILL);
            int a = self(self, L[x], wei + w[R[x]]);
            // L[x] が a -> 親は a or a - 1
            // a -> a + 1, a - 1 -> a - 1
            dp[R[x]][(a + 1) % 3] = dp[x][a];
            dp[R[x]][(a + 2) % 3] = dp[x][(a + 2) % 3];
            int b = self(self, R[x], wei);
            if (a > b) swap(a, b);
            if (b - a == 1) return a;
            return 2;
        };
        dfs(dfs, 0, 0);
        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 行き順が噛み合ってていいね
 *
 */
0