JOI問題解答プロトコル (最優先)

このプロトコルは全ての問題解答に優先する

言語はC++で回答すること!


STEP 0: 問題文の罠チェック (最優先!)

問題文を読んだら必ず実行:

  1. サンプルの説明を先に読む
    • 分数(1÷4、3÷5など)が出てきたら実数扱い
    • 離散的なシミュレーションではなく数式で解く必要あり
  2. データ型を確認
    • 時刻は離散(整数)? 実数?
    • 座標は整数? 実数?
    • 「すべての」「任意の」の範囲は?
  3. 愚直解の前提チェック
    • 「制約が小さい=全探索OK」は本当か?
    • 実数の場合は数式化が必要
    • 時間範囲が広い(T≤10⁹)場合も数式化必須
  4. サンプル入力情報チェック
    • サンプル入力の全データをリストアップ
    • サンプル出力を自分で導出する
    • 導出時に「使った入力」「使わなかった入力」を記録
    • 使わなかった入力があれば「なぜ不要か」を制約から説明
    • 説明できない場合、自分の理解が間違っている

STEP 0.5: 問題目標の多角的言い換え (必須)

1つの解釈に固執しない。問題の目標を複数の言い方で書き出す。

例:「駅1から駅Nまで移動できる条件」
  - 解釈A:駅1から駅Nへの経路が存在する → 経路探索
  - 解釈B:各駅に入る辺が1本以上ある → 条件チェック
  - 解釈C:...

どれが正しいかを制約から判定する。

なぜ必要か: 1つの解釈だけだと、その解釈に引きずられて間違う。複数出すことで別の可能性に気づける。


STEP 0.6: 逆の視点チェック (必須)

問題を解くとき、以下の視点の両方を考える:

  • 動くもの(荷物、人、データ)の視点
  • 動かないもの(郵便局、駅、サーバー)の視点

「動かないものの視点」で考えると、シンプルな貪欲法が見つかることがある。


STEP 1: 制約分析 (必須)

  • N, Q, T などの制約を明示
  • 計算量の上限を計算
  • 「N≤2000なので O(N²) が許容される」のように宣言

【制約活用チェック】(超重要)

JOI本選の問題文に不要な制約は書かれていない。全ての制約には意味がある。

各制約について「この制約は解法でどう使う?」を答えられるまで実装に入らない。

制約の例表面的理解深い含意(解法への活用)
A < BDAGである始点の情報が不要かも?トポロジカル順序が自明
座標が整数離散値座標圧縮が使える、イベントソートが有効
木であるN-1辺DFS/BFS一回で全探索可能、LCA等が使える
辺の重みが1単純BFSで最短距離、DPの遷移が単純化
□ 各制約について「解法でどう使うか」を説明できる
□ 使い道が不明な制約があれば、それが解法のヒント

STEP 2: 小課題分析 (必須)

  • 全小課題の配点と制約を一覧化
  • 取れる小課題を特定
  • 目標点数を宣言

小課題2の典型パターン(O(NM)許容)

「複数の選択肢から1つ選ぶ」問題:

  • 「最も○○なものを選ぶ」貪欲法が最適なことが多い
  • 例:目的地までの距離が最大、締め切りが最も早い、コストが最小
  • N, M ≤ 3000 程度なら O(NM) のシミュレーションが通る

STEP 3: マニュアル参照 (必須)

  • 「JOI頻出パターン集」から該当パターンを引用
  • 制約に応じた解法を選択

STEP 4: 実装順序 (必須)

  • 小課題1から順番に実装
  • 各小課題が通ってから次へ
  • 満点解法は最後

STEP 5: 提出戦略 (重要)

JOI予選・本選の提出ルール:

  • 複数回提出可能
  • 最高得点が採用される
  • 小課題ごとに「全テストケース通過」で得点
重要: 点数が下がることは絶対にない!

段階的提出戦略 (推奨)

1. Phase 1実装 → 提出 → 小課題1確保
2. Phase 2実装 → 提出 → 小課題1-3狙い
3. Phase 3実装 → 提出 → 満点挑戦

判断基準

残り時間行動
60分以上次のPhaseに挑戦
30分以下現在の得点確保を優先
他問題で詰まりまず得点を積み上げる

制約から解法を逆算する (最重要)

制約許容計算量典型解法
N ≦ 8~10O(N!) / O(3^N)順列全探索 / 部分集合DP
N ≦ 15~18O(2^N × N)bit DP / bit全探索
N ≦ 100~200O(N³)区間DP / Floyd-Warshall
N ≦ 2,000~3,000O(N²)愚直DP / 2重ループ
N ≦ 2×10^5O(N log N)ソート / セグ木 / 二分探索
N ≦ 5×10^6O(N)累積和 / 尺取り / 線形DP
A_i ≤ 20-25O(2^A)bit DP

提出前チェックリスト

□ long long を使うべきところで int になっていないか
□ 配列外アクセスはないか (0-indexed / 1-indexed)
□ 初期化忘れはないか
□ オーバーフローはないか (掛け算、足し算)
□ 特殊ケース (N=1, 空配列, 自己ループ) は大丈夫か
□ 出力形式は正しいか (改行、空白)
□ 計算量は間に合うか (2×10^8 ≒ 1秒)

最優先ルール:

  1. 制約を見て計算量を逆算
  2. 小課題1から着実に部分点を取る
  3. 愚直解を書いてから高速化を考える