結果

問題 No.3510 RPS Eliminations
コンテスト
ユーザー はじっこゆーれー
提出日時 2026-04-18 06:02:53
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
TLE  
実行時間 -
コード長 6,742 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,137 ms
コンパイル使用メモリ 204,152 KB
実行使用メモリ 157,696 KB
最終ジャッジ日時 2026-04-18 06:03:57
合計ジャッジ時間 14,887 ms
ジャッジサーバーID
(参考情報)
judge2_1 / judge1_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample -- * 1
other AC * 5 TLE * 1 -- * 22
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
const long long INF = 2e18;
long long add(long long a, long long b) {
    return min(INF, a + b);
}
long long mul(long long a, long long b) {
    if (a == 0 || b == 0) return 0;
    if (INF / a < b) return INF;
    return a * b;
}
struct Vec {
    long long v[3];
    Vec() { v[0] = v[1] = v[2] = 0; }
    Vec(long long r, long long p, long long s) { v[0] = r; v[1] = p; v[2] = s; }
};
struct Mat {
    long long m[3][3];
    Mat() { memset(m, 0, sizeof(m)); }
    Mat operator*(const Mat& o) const {
        Mat r;
        for (int i = 0; i < 3; ++i) {
            for (int k = 0; k < 3; ++k) {
                if (m[i][k]) {
                    for (int j = 0; j < 3; ++j) {
                        r.m[i][j] = add(r.m[i][j], mul(m[i][k], o.m[k][j]));
                    }
                }
            }
        }
        return r;
    }
};
Mat make_matrix(const Vec& A) {
    Mat M;
    M.m[0][0] = A.v[2]; M.m[0][2] = A.v[0];
    M.m[1][1] = A.v[0]; M.m[1][0] = A.v[1];
    M.m[2][2] = A.v[1]; M.m[2][1] = A.v[2];
    return M;
}
Vec operator*(const Mat& m, const Vec& v) {
    Vec r;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            r.v[i] = add(r.v[i], mul(m.m[i][j], v.v[j]));
        }
    }
    return r;
}
struct BIT {
    int n;
    vector<int> tree;
    BIT(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 = 20; i >= 0; i--) {
            int next_idx = idx + (1 << i);
            if (next_idx <= n && tree[next_idx] < k) {
                idx = next_idx;
                k -= tree[idx];
            }
        }
        return idx + 1;
    }
};
struct SegTree {
    int n;
    vector<Mat> tree;
    SegTree() {}
    SegTree(int n) : n(n), tree(4 * n) {
        for (int i = 0; i < 4 * n; i++) {
            for (int j = 0; j < 3; j++) tree[i].m[j][j] = 1;
        }
    }
    void update(int node, int start, int end, int idx, const Mat& val) {
        if (start == end) {
            tree[node] = val;
            return;
        }
        int mid = (start + end) / 2;
        if (idx <= mid) update(2 * node, start, mid, idx, val);
        else update(2 * node + 1, mid + 1, end, idx, val);
        tree[node] = tree[2 * node] * tree[2 * node + 1];
    }
    Mat query(int node, int start, int end, int l, int r) {
        if (r < start || end < l) {
            Mat id;
            for (int i = 0; i < 3; i++) id.m[i][i] = 1;
            return id;
        }
        if (l <= start && end <= r) return tree[node];
        int mid = (start + end) / 2;
        return query(2 * node, start, mid, l, r) * query(2 * node + 1, mid + 1, end, l, r);
    }
};
long long pow2[200005];
void solve() {
    int N;
    long long K;
    if (!(cin >> N >> K)) return;
    vector<int> A(N - 1);
    for (int i = 0; i < N - 1; i++) cin >> A[i];
    int V = 2 * N - 1;
    vector<int> L(V, -1), R(V, -1), parent(V, -1);
    BIT bit(N);
    vector<int> pos_to_node(N + 1);
    for (int i = 1; i <= N; i++) {
        bit.add(i, 1);
        pos_to_node[i] = i - 1;
    }
    for (int i = 0; i < N - 1; i++) {
        int p1 = bit.find_kth(A[i]);
        int p2 = bit.find_kth(A[i] + 1);
        int u = pos_to_node[p1];
        int v = pos_to_node[p2];
        int new_node = N + i;
        L[new_node] = u; R[new_node] = v;
        parent[u] = new_node; parent[v] = new_node;
        pos_to_node[p1] = new_node;
        bit.add(p2, -1);
    }
    int root = 2 * N - 2;
    vector<int> sz(V, 0), heavy(V, -1);
    auto dfs_sz = [&](auto& self, int u) -> void {
        if (u < N) {
            sz[u] = 1;
            return;
        }
        self(self, L[u]); self(self, R[u]);
        sz[u] = sz[L[u]] + sz[R[u]];
        if (sz[L[u]] >= sz[R[u]]) heavy[u] = L[u];
        else heavy[u] = R[u];
    };
    dfs_sz(dfs_sz, root);
    vector<int> head(V, -1), in(V, -1), tail(V, -1);
    int timer = 0;
    auto dfs_hld = [&](auto& self, int u, int h) -> void {
        head[u] = h;
        in[u] = timer++;
        if (heavy[u] != -1) {
            self(self, heavy[u], h);
            tail[u] = tail[heavy[u]];
        } else {
            tail[u] = u;
        }
        if (L[u] != -1 && L[u] != heavy[u]) self(self, L[u], L[u]);
        if (R[u] != -1 && R[u] != heavy[u]) self(self, R[u], R[u]);
    };
    dfs_hld(dfs_hld, root, root);
    SegTree initial_seg(V);
    vector<Vec> initial_leaf_vec(V);
    for (int i = 0; i < N; i++) {
        initial_leaf_vec[i] = Vec(pow2[sz[i] - 1], pow2[sz[i] - 1], pow2[sz[i] - 1]);
    }
    for (int u = N; u < V; u++) {
        int light = (L[u] == heavy[u]) ? R[u] : L[u];
        Vec light_val = Vec(pow2[sz[light] - 1], pow2[sz[light] - 1], pow2[sz[light] - 1]);
        initial_seg.update(1, 0, V - 1, in[u], make_matrix(light_val));
    }
    SegTree seg;
    vector<Vec> leaf_vec;
    auto get_path_W = [&](int h) -> Vec {
        int bottom = tail[h];
        Mat m = seg.query(1, 0, V - 1, in[h], in[bottom] - 1);
        return m * leaf_vec[bottom];
    };
    auto update_leaf = [&](int leaf_idx, Vec new_W) {
        leaf_vec[leaf_idx] = new_W;
        int curr = leaf_idx;
        while (curr != -1) {
            int h = head[curr];
            Vec top_W = get_path_W(h);
            int p = parent[h];
            if (p != -1) {
                seg.update(1, 0, V - 1, in[p], make_matrix(top_W));
            }
            curr = p;
        }
    };
    for (int target : {0, 1, 2}) {
        seg = initial_seg;
        leaf_vec = initial_leaf_vec;
        long long K_rem = K;
        string ans = "";
        bool possible = true;
        for (int i = 0; i < N; i++) {
            bool found = false;
            for (int c : {1, 0, 2}) {
                Vec v(0, 0, 0);
                v.v[c] = 1;
                update_leaf(i, v);
                long long ways = get_path_W(head[root]).v[target];
                if (K_rem <= ways) {
                    ans += (c == 0 ? 'R' : (c == 1 ? 'P' : 'S'));
                    found = true;
                    break;
                } else {
                    K_rem -= ways;
                }
            }
            if (!found) {
                possible = false;
                break;
            }
        }
        if (possible) cout << ans << "\n";
        else cout << "-1\n";
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    pow2[0] = 1;
    for (int i = 1; i <= 200000; i++) pow2[i] = min(INF, pow2[i - 1] * 2);
    int T;
    if (cin >> T) {
        while (T--) solve();
    }
    return 0;
}
0