結果

問題 No.3510 RPS Eliminations
コンテスト
ユーザー Nzt3
提出日時 2026-04-01 16:35:59
言語 PyPy3
(7.3.17)
コンパイル:
pypy3 -mpy_compile _filename_
実行:
pypy3 _filename_
結果
AC  
実行時間 836 ms / 2,000 ms
コード長 4,835 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 229 ms
コンパイル使用メモリ 85,376 KB
実行使用メモリ 233,216 KB
最終ジャッジ日時 2026-04-17 20:02:52
合計ジャッジ時間 21,488 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge3_1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 28
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

class FenwickTree:
    def __init__(self, size):
        self.tree = [0] * (size + 1)

    def add(self, i, delta):
        while i < len(self.tree):
            self.tree[i] += delta
            i += i & (-i)

    def find_kth(self, k):
        idx = 0
        for i in range(17, -1, -1):
            next_idx = idx + (1 << i)
            if next_idx < len(self.tree) and self.tree[next_idx] < k:
                idx = next_idx
                k -= self.tree[idx]
        return idx + 1


def solve():
    N, K = map(int, input().split())
    A = list(map(int, input().split()))

    fenwick = FenwickTree(N)
    for i in range(1, N + 1):
        fenwick.add(i, 1)

    left_child = [0] * (2 * N - 1)
    right_child = [0] * (2 * N - 1)
    node_at_pos = list(range(-1, N))

    node_id = N
    for a in A:
        pos1 = fenwick.find_kth(a)
        pos2 = fenwick.find_kth(a + 1)

        left_child[node_id] = node_at_pos[pos1]
        right_child[node_id] = node_at_pos[pos2]

        node_at_pos[pos1] = node_id
        fenwick.add(pos2, -1)
        node_id += 1

    root = 2 * N - 2
    INF = 2 * 10**18

    # --- 簡略化されたDP計算 ---
    # dp[u] : 部分木 u が特定の文字になる組み合わせの総数
    dp = [1] * (2 * N - 1)
    for i in range(N, 2 * N - 1):
        L = left_child[i]
        R = right_child[i]
        # 合流のたびに組み合わせが2倍になる (オーバーフロー防止のためINFで頭打ち)
        dp[i] = min(INF, dp[L] * dp[R] * 2)

    # 'P'=0, 'R'=1, 'S'=2
    win = [[-1, 0, 2],
           [0, -1, 1],
           [2, 1, -1]]

    def solve_for_target(target):
        if dp[root] < K:
            return "-1"

        res = [-1] * N
        curr_K_val = K  # nonlocalの代わりにローカル変数として管理

        # 各ノードの計算結果(どの手を選択したか)を保持
        realized = [-1] * (2 * N - 1)

        # スタックには [現在のノード, そのノードに渡されたways, 処理状態] を格納
        # 状態: 0=初回訪問, 1=左の子の処理完了後, 2=右の子の処理完了後
        root_ways = [0] * 3
        root_ways[target] = 1
        stack = [[root, root_ways, 0]]

        while stack:
            # stack[-1] で現在の要素を参照(popはまだしない)
            curr = stack[-1]
            u, ways, state = curr[0], curr[1], curr[2]

            # --- 葉ノード(ベースケース)の処理 ---
            if u < N:
                stack.pop()
                for c in range(3):
                    if curr_K_val <= ways[c]:
                        res[u] = c
                        realized[u] = c
                        break
                    curr_K_val -= ways[c]
                continue

            L = left_child[u]
            R = right_child[u]

            # --- 内部ノードの処理(状態管理) ---
            if state == 0:
                # 1. 左の子へ行く前の準備 (ways_L の計算)
                ways_L = [0] * 3
                # 元のコードの2重ループを定数時間で展開(高速化)
                ways_L[0] = min(INF, (ways[0] + ways[2]) * dp[R])  # P
                ways_L[1] = min(INF, (ways[0] + ways[1]) * dp[R])  # R
                ways_L[2] = min(INF, (ways[1] + ways[2]) * dp[R])  # S

                curr[2] = 1  # 状態を更新して左の子をスタックに積む
                stack.append([L, ways_L, 0])

            elif state == 1:
                # 2. 左の子から戻ってきた。次に右の子へ行く準備 (ways_R の計算)
                rL = realized[L]
                ways_R = [0] * 3
                # 勝敗ルールに基づいて realized_L に対応する K 番目の重みを分配
                if rL == 0:  # 左がPなら、右がRで全体がP、右がSで全体がS
                    ways_R[1], ways_R[2] = ways[0], ways[2]
                elif rL == 1:  # 左がRなら、右がPで全体がP、右がSで全体がR
                    ways_R[0], ways_R[2] = ways[0], ways[1]
                else:  # 左がSなら、右がPで全体がS、右がRで全体がR
                    ways_R[0], ways_R[1] = ways[2], ways[1]

                curr[2] = 2  # 状態を更新して右の子をスタックに積む
                stack.append([R, ways_R, 0])

            else:  # state == 2
                # 3. 右の子からも戻ってきた。自身の realized を確定させて pop
                stack.pop()
                realized[u] = win[realized[L]][realized[R]]

        return "".join("PRS"[c] for c in res)

    print(solve_for_target(1))  # Target: R
    print(solve_for_target(0))  # Target: P
    print(solve_for_target(2))  # Target: S


if __name__ == '__main__':
    T = int(input())
    for _ in range(T):
        solve()
0