こんにちは、高柴です。ふだんは業務システムを作っているソフトウェアエンジニアです。
AtCoder で水色になりました。ABC の E 問題まで、自力で解ける回が増えてきたところです。
振り返ってみると、特別な才能があったわけではありません。やったことは単純で、E 問題で使われる「技」を、一つずつ身につけていっただけです。
その経験をもとに、技を一つずつ図で覚えられる練習サイト「アルゴ図解」を作りました。
この記事では、E が解けるようになるまでに大事だと思ったことと、サイトの中身・作り方を書きます。
E 問題が解けないのは、たいてい「技を知らない」から
E 問題が解けないとき、原因は大きく 2 つあると思っています。
- その問題で使う技を、そもそも知らない
- 技は知っているのに、この問題で使うと気づけない
1 つ目は、知ってしまえば終わりです。累積和も、二分探索も、Union-Find も、知らないと絶対に思いつけませんが、一度覚えれば次からは使えます。地頭の問題ではなく、知っているかどうかの問題なんですよね。
厄介なのは 2 つ目でした。技を覚えたつもりでも、本番の問題文を読んだときに「あ、これ累積和だ」と気づけない。解説を読んで「知ってる技じゃん……」となるのが一番悔しいパターンです。
なので、技を覚えるときは、中身と一緒に「どんな問題文のときに使うか」をセットで覚えるのが大事だと思っています。
問題文のどこを見れば、技がわかるか
たとえば、こんな手がかりがあります。
| 問題文の特徴 | まず疑う技 |
|---|---|
| N ≤ 8 くらいで、並べ方を全部試せそう | 順列全探索 |
| N ≤ 20 くらいで、選ぶ・選ばないを全部試せそう | bit 全探索、bit DP |
| N ≤ 40 くらいで、bit 全探索だと少し大きい | 半分全列挙 |
| 区間の和を何度も聞かれる | 累積和 |
| 区間にまとめて足す操作がたくさんある | いもす法 |
| 「最小値の最大化」「最大値の最小化」 | 答えで二分探索 |
| グリッドや重みなしグラフの最短距離 | BFS |
| 移動のコストが 0 か 1 だけ | 01-BFS |
| 重み付きグラフの最短距離 | ダイクストラ法 |
| 全頂点の組の最短距離で、N ≤ 400 くらい | ワーシャル–フロイド法 |
| 「くっつける」「同じグループか」 | Union-Find |
| K が 10^18 回のような、とんでもない回数の操作 | ダブリング、周期を見つける |
| 「何通りあるか、998244353 で割った余り」 | DP、二項係数 nCr |
全部が当てはまるわけではありませんが、これを知っているかどうかで、問題文を読んだあとの迷い方がまったく違います。
特に、N の上限は一番のヒントです。N ≤ 20 なら 2^20 ≒ 100 万なので全部試せる、N ≤ 2×10^5 なら O(N log N) くらいまで、というように、計算量から逆算して技を絞り込めます。
身につけた技(サイトの目次)
水色まで、つまり E 問題までに必要だと思った技を、覚える順に並べるとこうなります。サイトもこの順番です。
- 全探索の仲間:計算量の見積もり、全探索、シミュレーション、bit 全探索、順列全探索、再帰、半分全列挙
- 区間と探索:累積和、2 次元累積和、いもす法、二分探索、答えで二分探索、尺取り法、ソートと貪欲法、座標圧縮
- データ構造:スタック・キュー・deque、辞書と集合、優先度付きキュー、Union-Find、BIT と転倒数、セグメント木、ダブリング
- グラフ:DFS、BFS、01-BFS、ダイクストラ法、ワーシャル–フロイド法、トポロジカルソート、最小全域木、二部グラフ判定、木 DP、LCA、周期の検出
- DP:DP 入門、グリッドの経路 DP、ナップサック、LCS と編集距離、LIS、bit DP、区間 DP、桁 DP、確率と期待値の DP
- 数学:GCD と LCM、N 進数、約数と素因数分解、エラトステネスの篩、繰り返し二乗法、逆元と nCr、包除原理
- 文字列:ランレングス圧縮、ローリングハッシュ
全部で 51 個です。多く見えますが、一つずつなら意外といけます。自分も一気に覚えたわけではなく、解けなかった問題の解説で出てきた技を、その都度一つずつ自分のものにしていきました。
サイトでこだわったこと
1. 全部「コマ送りの図」で見せる
アルゴリズムは、文章で読むより、動いているところを見たほうが圧倒的にわかります。たとえば BFS なら、キューから 1 つ取り出して、隣を塗って、キューに入れて……という流れを、1 コマずつ ▶ で進めながら見られます。実行中のコードの行も光るので、図とコードの対応がわかります。
入力欄の数字を変えると、その入力で図が作り直されます。自分で入力をいじって「こういうときはこう動くのか」と確かめられるのが、覚えるうえでかなり効きました。
2. 「使いどころ」と「実装の手順」を必ず書く
上で書いたとおり、技は「いつ使うか」がわからないと本番で出てきません。なので、全トピックの先頭に、
- どんな問題文のときに使うか(問題文の例つき)
- 使えないときに、代わりに使う技
- 番号付きの実装の手順
- そのまま提出できる完成形のコード
- 提出前のチェックリスト
を入れました。図で仕組みを理解したあと、手順どおりに書けば実装できる、という流れです。
3. ブラウザの中で Python を動かして採点する
練習問題は 87 問あって、サイトの中で Python のコードを書いて、その場で採点できます。サーバーは使っていません。Pyodide(ブラウザで動く CPython)を Web Worker の中で動かしています。
// Python を動かす Web Worker。Pyodide を CDN から読み込む
const PYODIDE_URL = 'https://cdn.jsdelivr.net/pyodide/v0.29.5/full/';
async function boot() {
if (pyodide) return pyodide;
const mod = await import(`${PYODIDE_URL}pyodide.mjs`);
pyodide = await mod.loadPyodide({ indexURL: PYODIDE_URL });
// 標準入力にテストケースを流し込み、標準出力を受け取る関数を Python 側に用意しておく
pyodide.runPython(`...`);
return pyodide;
}
Worker に分けたのは、無限ループ対策です。提出されたコードが無限ループしても画面が固まらないように、別スレッドで動かしておいて、6 秒たっても終わらなければ Worker ごと terminate() で捨てて、TLE として扱います。次の提出のときに、また新しい Worker を作り直します。
最初の 1 回だけ、Python の準備に 5〜10 秒かかるのが弱点です。
4. 続けたくなる仕掛け
正直、一人で黙々と技を覚えるのは途中でだれます。なので、ゲームっぽい仕掛けをいろいろ入れました。
- 経験値とランク:図を見る・クイズに答える・AC するとたまっていき、ランクは AtCoder と同じ色(灰 → 茶 → 緑 → 水 → 青 → 黄 → 橙 → 赤)で上がっていきます
- AC したときの紙吹雪:ヒントを見ずに AC するとボーナスが付きます
- バッジと連続学習日数、全員に同じ問題が出る「今日の 1 問」
- 技当てクイズ:問題文を見て、使う技を 60 秒で当てるミニゲーム。上で書いた「問題文から技に気づく力」を鍛えるためのものです
進み具合はブラウザに保存されるだけで、ログインはいりません。
5. AtCoder の過去問につなげる
各トピックには、その技を使う AtCoder の過去問へのリンクを付けました。全部で 230 問です。サイトで技を覚えたら、本物の問題で練習できます。
作り方
サイトは Vite + TypeScript の静的サイトで、Cloudflare Workers で公開しています。サーバーもデータベースもないので、公開にかかるお金はゼロです。
トピックは 1 ファイルに 1 アルゴリズムで、文章・図・クイズ・練習問題・過去問をデータとして書く形にしました。図は「全コマの状態を先に計算しておいて、1 コマずつ描く」という 2 段構えにしています。こうしておくと、◀ で戻るのも簡単です。
設計の進め方は AI(Claude Code)と相談しながら決めて、実装も一緒に進めました。そのぶん、間違いを機械で見つける仕組みには力を入れています。
- 模範解答を本物の Python で実行して確かめる:練習問題の模範解答を、全テストケース(525 ケース)に通してから公開しています
- 過去問のタイトルを照合する:リンク先の問題名が、AtCoder の実際のページと合っているかを確かめています
- 図の文字の重なりを自動で見つける:全部のコマを画像にして、文字の重なりやはみ出しを一覧にするスクリプトを作りました。ランダムな入力でも 0 件になるまで直しています
アルゴリズムの解説サイトで一番まずいのは、解説や模範解答が間違っていることだと思うので、ここは手を抜かないようにしました。
数字で見るとこんな感じです
| 数 | |
|---|---|
| トピック(技) | 51 |
| コマ送りの図 | 161 |
| クイズ | 152 |
| 練習問題 | 87 問(525 ケース) |
| AtCoder の過去問リンク | 230 問 |
おわりに
E 問題が解けないと、自分には向いていないのかなと思ってしまいがちです。でも、少なくとも水色くらいまでは、才能より「技を知っているか」「使いどころに気づけるか」の勝負だと思います。そして技は、一つずつなら必ず覚えられます。
これから緑や水色を目指す人の役に立てばうれしいです。
最後まで読んでいただき、ありがとうございました。