【色変】全完黄パフォで入水しました!
一昨日5/3(日)のABC166で初の全完を果たし、さらに黄パフォで入水いたしました!
そこで、他の競プロerもすなる色変記事というものを、私もしてみむとてするなり、です。
ただし、読んでいただく前に一つ注意書きを。
この色変記事を書くにあたって、十数人の方の色変記事を読ませていただいたのですが、
そうして思ったのは「精進の仕方は十人十色」だということです。
ですので、以下に書かれている内容は、「おすすめの精進法」ではなく、あくまでも「精進の仕方の一つ」として読んでいただければ幸いです。
私自身のことに関しては、前回の記事で書きましたので、もしご興味のある方はそちらも読んでいただけると嬉しいです。
各種精進データ
入水した現在の精進の状況については以下の通りです。
入水までに勉強したアルゴリズム
はい、色変記事あるあるです。
書き漏れがないようにプログラミングコンテストチャレンジブック(通称:蟻本)やAtCoder Tagsのカテゴリ分類を眺めながら、自分の知っているかつ使えるアルゴリズムを全列挙しておきます。
そしてそれらを、水色になるために重要そう(Lorent調べ)な順に並べ直したいと思います。
また、自分がそのアルゴリズムを初めて勉強したときに読んだ記事、見た動画の中で特にわかりやすかったもののリンクを貼っておきます。
☆☆☆:入緑でも確実に必要になるはず
☆☆★:まあまあよく使う
☆★★:数回使ったことがある
★★★:コンテストではまだ一度も使ったことがない
前提として
- 計算量の見積もりができる
- アルゴリズムを考えて、問題文の制約で間に合うか正しく判断できる
- 基礎でもあり、一番難しいところでもあるかも…
- W - 2.06.計算量
- 計算量オーダーの求め方を総整理! 〜 どこから log が出て来るか 〜 - Qiita
- チャート式 基礎からの数学Ⅰ+A ←基本的な順列・組合せの知識は必須
☆☆☆:入緑でも確実に必要になるはず
for loopによる全探索
- 基礎中の基礎。競プロ始めた人が一番初めに学ぶ探索手法と言っても過言ではない。
累積和
- 適切な前処理によって区間和がO(1)で求められるようになる。計算量を落とす基本テクニック。慣れないと添字がややこしい。
- 累積和を何も考えずに書けるようにする! - Qiita
深さ優先探索(DFS)
- 汎用性が高すぎる。グラフではもちろん、n重のfor文を書きたいと思ったときに大抵これが使える。私の感覚だが、グラフ以外で使うのは、樹形図を書けるとき。
- DFS (深さ優先探索) 超入門! 〜 グラフ・アルゴリズムの世界への入口 〜【前編】 - Qiita
- DFS (深さ優先探索) 超入門! 〜 グラフ・アルゴリズムの世界への入口 〜【後編】 - Qiita
- 再帰関数を学ぶと、どんな世界が広がるか - Qiita
素数判定(試し割り)
- O(√n)でできることを認識するのが重要。計算量の見積もりで必要になることも多い。
bit全探索
- bit演算を活かした最も基礎的なアルゴリズム。bitとはn個のflagを立てているイメージでよいと思う。O(2n)で間に合うときは私は反射的にこれを思い浮かべてしまう。計算量からメタ的にアルゴリズムを考えるのは賛否両論あるが。
- ビット演算 (bit 演算) の使い方を総特集! 〜 マスクビットから bit DP まで 〜 - Qiita
順列全探索
- C++でいえばnext_permutation、Pythonでいえばitertools.permutations。これも制約が小さそうなときに使う。
- AD - 3.06.その他の機能
二分探索
- 通称「にぶたん」。シンプルかつ奥が深い。lower_boundだけがにぶたんじゃない。単調性さえあれば使える。しかもO(logn)。つよつよ。
- 二分探索アルゴリズムを一般化 〜 めぐる式二分探索法のススメ 〜 - Qiita
- 蟻本3-1
modについての知識
- 「ただし、1000000007で割った余りを求めよ」みたいなやつ。
- 加減乗除、累乗(二分累乗法)、二項係数あたりまではライブラリ化しておくとよい。
- modの世界での除算を考える際にフェルマーの小定理を理解する必要がある。
- AtCoder解説放送ライブラリ集 mint
- 「1000000007 で割ったあまり」の求め方を総特集! 〜 逆元から離散対数まで 〜 - Qiita
☆☆★:まあまあよく使う
ナップサックDP
- DP入門編。これを初めて理解できるようになるまでに、かなりの時間を要した。今でもあまり得意ではない。
- 二次元までのDPならDPテーブルを自分で書いてみるのがよい。恥ずかしながら、私は今でもDPの問題を解くときに、考察ノートにDPテーブルを書かないと解けない。逆にいえば、DPテーブルを書けたら解ける。
- 大事なのは、初期値、遷移の仕方、埋めていく順序の3つ。
- 漸化式、メモ化再帰、どちらの考え方も重要なので両方学んでおくとよい。
- 動的計画法超入門! Educational DP Contest の A ~ E 問題の解説と類題集 - Qiita
- 典型的な DP (動的計画法) のパターンを整理 Part 1 ~ ナップサック DP 編 ~ - Qiita
- プログラミングコンテストでの動的計画法
エラトステネスの篩
- 素数列挙や、多くの数を素因数分解するときに使う。発想としてはとてもシンプル。高校の教科書にも出てきた覚えがある。O(nloglogn)になる理由をしっかりとは理解できていない。
- ABC152Eの解説放送
幅優先探索(BFS)
- 辺の重みが全て1であるときの最短路問題に使える。普通にグラフの探索をするときも使えるが、DFSで書いた方が実装が軽い場合が多いと思われる。名前からしてDFSと双璧を為すかと思いきや、DFSに押されがちなイメージ。
- 0-1BFSも勉強しておくとよい。辺の重さが0 or 1のときに使う。dequeを用いて0の辺を優先的に探索していく。
- BFS (幅優先探索) 超入門! 〜 キューを鮮やかに使いこなす 〜 - Qiita
- 01-BFSのちょっと丁寧な解説 - ARMERIA
尺取り法
- 「とある条件を満たす区間を求めよ」のような問題でよく使う。ながたかなさんの尺取り法実装の†ソウル†の記事、ぜひとも読んでほしい。大好きな記事。
- 尺取り法の実装で嵌ったあの日の涙を数え切れないあなたにお送りする、尺取り法実装の † ソウル † です。 - Qiita
- しゃくとり法 (尺取り法) の解説と、それを用いる問題のまとめ - Qiita
Union-Find Tree
- グループを作り、ある2要素が一緒のグループに属するかが高速に判定できるデータ構造。初めて勉強したときは、「それで……どう使えるの?」となったが、 かなり汎用性が高い。閉路検出もできる。
- B: Union Find - AtCoder Typical Contest 001 | AtCoder
- ABC157Dの解説放送
imos法
- 一定区間にある数を足すという操作をするアルゴリズムで、累積和とともに用いる。次元の拡張もできる。とある暖色コーダーさんがimos法のことを「離散微分」とおっしゃっていて、イメージしやすいなと感じた。
- いもす法 - いもす研 (imos laboratory)
xorの性質理解
- 昔はxor出てくるだけで「うっ…」となっていたが、多く解いているとなんとなく式変形にも慣れる。とりあえず以下の2つの性質を理解しておけばよいと思う。
- a ^ a == 0、
- a ^ b <= a + b(等号成立は、右辺の繰り上がりのないとき)
- 競技プログラミングにおけるXORのTips - Qiita
-
- 負辺がないときの単一始点最短路問題に使える。本質は「最短路が確定した順に更新していくDP」と捉えている。「拡張Dijkstra法」はDijkstra法を拡張しているわけではなく、DPテーブルに距離以外の状態を持たせたもの。
- 蟻本2-5
- ABC164Eの解説放送
☆★★:数回使ったことがある
Warshall-Floyd法
Bellman-Ford法
- 負辺があるときの単一始点最短路問題に使える。負閉路の検出にも使える。実装もまあまあシンプル。
- Bellman-Ford法の解説 - Qiita
桁DP
- 未満フラグという状態変数を理解することが重要。
- 「未満フラグが立っている」=「どんな数字を選んでもよい」
- xorの問題でもよく使われる。
- まだサクサクとは書けない。
- Digit DP 入門 - torus711 のアレ
Fenwick Tree(BIT)
- 区間和を高速に計算できる、かつ、ある要素にある数字を加えていくことができる。
- 今のところSegment Treeの軽量版、累積和の強いやつみたいなイメージ。あっているかは不明。
- ABC136Fの解説放送
- 蟻本3-3
bitDP
- 例題として、巡回セールスマン問題という有名問題が用いられることが多い。
- 状態集合を添字として持つDP(定義は人によって曖昧らしい)。
- 蟻本3-4
三分探索
- 連続関数の極値を求める手法。二分でダメなら三分すればいいじゃない。
- 通称「さぶたん」(嘘です、聞いたことありません)。
- 三分探索 - 忘れても大丈夫
★★★:コンテストではまだ一度も使ったことがない
座標圧縮
- 通称「座圧」。今まで解いてきた問題では、まだ有用性を感じたことはない。
- 蟻本3-2
全方位木DP
- 全頂点を始点としてDFSすれば解けるが、計算量が間に合わないときに、こいつの出番。
- 両方向累積〇〇を取れば、逆元がなくても実装できる。
- 何を読んでも理解できずに困っていたとき、最後に辿り着いたのはsnukeさんの解説だった。ぜひご視聴を。
- ABC160Fの解説放送
- †全方位木DP†について - ei1333の日記
- 【全方位木DP】明日使える便利な木構造のアルゴリズム - Qiita
区間DP
- 精選100問にあるので軽く勉強しただけ。まだあまり理解できていない。
- 【動的計画法】連鎖行列積 - プログラミング原人の進化論
Kruskal法
精進の内容
これは私の精進グラフです。
不思議なグラフの形ですね。経緯が気になる方は自己紹介記事をどうぞ。
以下、2020年3月から入水するまでに行った精進の内容についてです。
蟻本の購入
AtCoderProblemsのBootCamp全埋め
- ものすごく力になりました。ひたすら全探索をする問題が多かったです。これを通して「まず全探索を考えてみる」という発想が自然と身についたように感じます。
あさかつ、よるかつに毎日参加する
けんちょんさんの蟻本記事
- これは手元に蟻本あってこその記事です。私は蟻本を買う前にこの記事を読んだとき、挙げられているキーワードをヒントに以下の問題を解け、という記事だと勘違いしておりました。
- そもそも蟻本が前から難易度順に並んでいるかと言われると、そうではないような気がするので、この記事もきっと、前から順に解いていくといったことはしない方がよいと思われます。私はそうして心が折れました。
- 蟻本を勉強した際に、そのアルゴリズムについて理解を深めたいとき、この記事ほど有用なものはありません。
E869120さんの精選100問
- 水色コーダーになるために解くべき100問をまとめてくださっています。
- 7割くらい埋めました。個人的にはナップサックDP以外のDP、最小全域木、その他のテクニックあたりは余裕のある方が手をつければよいと思います。私はやれていません。
AtCoderProblems Recommendation Medium
- 私の最近の精進のメインコンテンツです。自分のレート帯なら約50%の確率で解けると推定された問題が表示されます。素晴らしい機能です。
- 疲れたときはEasyを進めます。Hardは無謀です。
精進のTips
解説ACは悪ではない
解説ACとは、分からなかった問題の解説を読んでからACすることを指します。
「解説ACをできる限りしたくない。解けないのはまだ私の実力が足りていないからだ。」
→気持ちは大変分かります。私もその一人でした。しかし一度見た問題をわからないままにしておくことの方が私にとっては気持ち悪いのです。その問題を解説ACしておくことで実力を高めましょう。
「わからない問題があったら解説を見て理解し、次に出会ったときに解けるようにしておく」
→それができたら一番よいと思います。解説ACしてしまった問題は区別できませんもんね…。ただ、解説を読んで理解しただけで、今後その問題と再び出会った時にACを取れる実装ができるでしょうか。少なくとも私にはできません。せっかく解説を読んで理解したならば、その流れで実装までしてしまった方がお得ではありませんか。
私の実践方法についてです。
青diffまでの問題は、一目見てしまったら、何が何でもACを取っておくようにしています。なぜ青diffまでと決めているかといいますと、自分の理解度的に、それ以上のdiffの問題は解説を読んでも理解し難く感じたのと、継続的にあさかつやよるかつに参加していれば、解説ACをした問題とも再び出会える可能性が高いからです。最近は復習キューをToDoアプリで管理するようにしています。
また、解説ACをする際に、写経は絶対にしません。初めから終わりまで自分で書いたコードでACできるようになることを重視しています。解説を読んで十分に理解したと思っても、実際にコードを書き始めると、意外と書けないという経験はありませんか?自分で書けない部分=理解し切れていない部分なので、改めてその部分の解説を重点的に、しっかり理解できるまで読みましょう。写経しないと分からない問題が多く感じたら、解説ACの閾値diffを下げればよいかと思います。
解けた問題の復習もしっかり行う
解けた問題についても、解説pdfや解説放送、また他の競プロerさんが書かれている解説ブログを見たりして、実装上より簡潔に書けそうなテクニック等を探すということを意識して行っています。
また、自分の解き方とは異なる解法があれば、それも理解して書けるようにしています。一つの問題を多面的に見る力を養うことで、考察力も上がります。
考察パートと実装パートはしっかり分ける
ある程度難しい問題になってくると、曖昧な考察のままコードを書き始めたところで、うまくいくことは少ないです。
手元に紙とペンを用意して、しっかりと考察しましょう。
考察で行き詰まった時は、
小さいケースでシミュレーションして特徴を捉える
全探索をすることを考えたときに、どの部分で計算量が落とせそうかを考える
とうまくいく場合が多いかと思います。
また、最後にコーナーケースが通るかは確認しておくようにしましょう。
そしてどう実装するかというイメージが固まってきた段階で、やっと実装パートに入るようにしています。きちんと考察できていれば、実装にはそれほど時間はかかりません。
考察が詰め切れていないまま実装し始めると、最悪の場合、実装途中に方針そのものが間違っていることに気付き、全部書き直しになってしまうということにもなりかねません。
Twitterを始めよう
もしこの記事を読まれている競プロerさんで、Twitterをされていない方がいたら、すぐにでも始めましょう。
多くの競プロerはTwitterをしています。特にコンテスト前後のタイムラインはとてつもない流速です。競プロ界隈で話題となったワードがトレンド入りすることもしばしばあります。 また、AtCoder公式情報もTwitterが最速です。
Twitterをしていると、同レート帯の競プロerがどういう精進をしているのか、その日のコンテストに出た問題の多種多様な解法、実装のちょっとしたテクニック、など競プロに関する様々な情報が自然と得られます。
わからないことをTwitterに投げると大抵優しい競プロerさんが丁寧に教えてくださります。
競プロタイムラインは温かいです。
「あなたがTwitterをしている間にライバルは競技プログラミングの問題を解いています。」 と言われて焦ってしまうこともあるとは思いますが、私はTwitterも精進の一貫と考えます。
おわりに
この色変記事で、多くの競プロerさんにとって少しでも役に立つ情報をお伝えできれば幸いです。
最後までお読みいただきありがとうございました。
これからもぜひお互いに切磋琢磨していきましょう。
みんなで黄色くらいになって、みんなで「緑の頃が懐かしいなあ」って言いたい https://t.co/I2U5zWJ8by
— Lorent (@lorent_kyopro) 2020年4月25日