精進について
サーバルだよ!
競プロの精進について書くよ。
精進の仕方や、精進に対する考え方はいろいろあるから、あくまで私の意見だと思って読んでね。
■3行でまとめて
・復習が大事。解けた問題も解けなかった問題も、解説やいろんな子の実装を見てみる
・典型を身につけるのは大事。ABCは解説ACでもいいので解く
・写経はできればしない。一回自分で書いてみてから他の子の実装をパクる
■モチベーションについて
レートがついて他の子と競う以上、やっぱりレートが下がると面白くないよね……。
私も最近は下がってこそないけど全然上がらなくて面白くないよ……。
モチベーションが低いときに無理してコンテストに出ても成績は悪くなりがちだから、そういう気分のときはしばらくコンテストに出ないというのももちろんありだよ。
だけど、私には「コンテストに出て悔しい思いをして、解けなかった問題をちゃんと復習する」って方が合ってるから、できるだけコンテストには出るようにしてるんだ。
■パフォーマンスを上げるには
パフォーマンスを上げるためには「簡単な問題をよりはやく解く」「より難しい問題を(どうにか)解く」の少なくともどっちかが必要だよ。
本当に目指すべきは「難しい問題を解く」の方で、「簡単な問題をはやく解く」っていうのは、難しい問題を考える時間を残すために必要なことだね。
・自分の色未満のdiffの問題を、考察も実装も悩まずに解けるようにする
・自分の色のdiffの問題を解けるようにする
あたりを目標にするといいんじゃないかな。
私たちが青の頃は400~600点を埋めてたよ。このあたりの難易度を一通り埋めれば、典型にはだいたい触れられると思う。
水未満なら300点400点あたりかな?
コノハ「これでA[BRGP]Cの500点問題も全て解き終わりましたね」
— 競技プログラミングをするフレンズ (@kyopro_friends) March 31, 2018
ミミ「自力AC率は19/23で82.6%ですか。微妙な数字ですね、博士」
コノハ「そうですね。次の難易度に進むべきかどうか聞いてみるですよ」
次に解くべきは
■考察パートについて
一番大事なのは「自分がコンテスト中に解けなかった1問」を解けるようになることだよ。
私が復習するときは
・知識が足りなかったなら覚えて、それを使う関連する問題を(あれば)解く
・知識は足りていたけど、考察できなかったときは、「どうすれば思いつけたか」を考える
ってことを考えながらしてるね。
解説ACについては、ABCの問題で1時間考えて解けないなら、知識が足りない可能性が高いから解説を読んだ方がいいと思うよ。
典型を知らない状態から自分で発明できれば、多分もう忘れることはないと思うけど、時間は有限だからね……。
逆にAGCは、C問題あたりまでなら特別難しい知識はいらない問題が多いから、じっくり考えるのもあり。私はこっちもすぐ解説を読んじゃうけど…………。
■どうすれば思いつくのか?
「どうすれば思いつくか?」にはいろんなアプローチって、例えば私がよく考えるのはこの2つ。
・簡単な部分問題から考える(もし与えられるグラフが木なら解ける。一般のグラフの場合は……)
・愚直解法を考える(O(N^3)のDPはすぐわかるけどN≦2000だから間に合わない。無駄な計算を省くには……)
他にも、計算機科学?に詳しい子は
・解けない問題を考える(もしこの条件がないとNP完全になって解けないから、この条件をうまく使う必要があって……)
みたいな考え方をすることもあるらしいけど、私にはよくわかんないや。
■実装パートについて
AtCoderに限れば実装が大変な問題はそんなに出ないから、「実装が大変そう」って思ったらもっと解法が整理できないか考えてみるのが1つの手だね。
もちろん難しい実装をきっちりやりきる力も大事だけど、難しい実装に手をつけてバグらせたら大変だし、それが嘘解法だった日には目もあてられないよ…………。
私はコンテスト中には「これよりいい解法が思い付けそうになくて、今の難しい実装をバグらせずに通せる自信がある」ってときだけ、難しい実装に手をつけることにしてる……つもりなんだけどな~。
■解説ACと写経について
写経って言葉をみんながどういう意味で使ってるのかよく知らないけど、私は「誰かのコードを横に見ながらコードを書くこと」はほとんどしないよ。
誰かの実装を見たり解説を読んだら、自分の中でよく噛み砕いて、なにをやっているのかを理解してから何も見ずに1から書くのが好きだからね。
解法・アルゴリズムを本当に理解したなら、(少なくとも、理解したはずのその瞬間には)なにも見ずに書けるようになるはずだと私は思ってるし、特に、できれば「なんでこれでうまくいくのか」まで分かるようにしておくと、応用の幅がぐっと広がるはず!
もちろん自分で書ききったあとは、もう1回他の子のコードを参考にしながら、書き直すのは大事だよ。細かい実装のテクニックを身につけるのにも役立つし、「自分はこう書いてしまったけど、こうするともっとスッキリ書ける」っていうのを確かめられる絶好の機会だもんね。(実装のテクニックだと「めぐる式二分探索」が一番有名なのかな?)
他にもACがはやい方から何人かのコードは、びっくりするくらい簡潔なことが多いから参考になるよ! 簡潔すぎてよくわからないこともあるけど……。
■復習について
解けなかった問題だけじゃなくて、解けた問題も復習するのは大事だよ。自分が解いたのよりもっと簡単な方法があったりするかもしれないし。
公式の解説pdfだけじゃなくていろんな解説記事を読むのがいいよ。
ずっと前、ガイドさんが私に勉強の仕方を教えてくれたときに、「よくわからないことがあったら、10種類くらい解説を読んでみると、そのうち1つくらいは自分にとって分かりやすいものがあるはず」って教えてくれたんだ。
10種類……はさすがにできてないかもしれないけど、1つや2つの解説を読んでわけがわからなくても諦めないようにはなれたはず。
そんな感じで私は精進してるよ!
なんだか精進の話とはちょっとズレてる気もするけど、参考になるかな?