一種程序設計競賽的訓練方法(譯)


原文地址

Rating從1000到2400+

2019年5月7日

Masataka Yoneda/E869120

1. 自我介紹

親愛的CF社區:

2019年4月20日,在14場比賽后,我終於達到了grandmaster,rating 2426。在最后一場比賽之前,我很遺憾rating是2399,距離成為粉名只差1分。所以上一場比賽(Forethought Future Cup Elimination Round) 是我印象最深的比賽之一。感謝CF舉辦這些比賽,感謝友善、出色且給人留下深刻印象的CF社區接受我的博客。

如今,我也想給CF社區做一點貢獻,因為我之前在CF社區收獲了很多,心里十分感激。我思考了很長時間“如何給CF做貢獻”,或者說以一種合適的方式給CF做貢獻。我想到了:介紹一種從灰名到粉名的練習方法。

現在,我要解釋如何成為一個紅名大佬。

2017年7月,我寫了一篇博客解釋如何到紫名(http://codeforces.com/blog/entry/53341) 。憑借這篇博客,我得到了181個贊,但那里面有很多語法錯誤,而且還有幾個地方沒有解釋清楚。我很抱歉自己不擅長英語,也不是一個很好的作者。這次的博客可能還是有一些錯誤,但我努力使它更易讀易懂。感謝你的合作、陪伴。

這次,我要分幾個步驟進行講解,因為rating范圍有好幾個,大部分人並不能一步就從灰名到達粉名,我也不能。所以這次我要分成下面的四個步驟:

  • Rating \(1000 \to 1400\),從灰名到青名
  • Rating \(1400 \to 1900\),從青名到前10%的選手
  • Rating \(1900 \to 2200\),從前10%選手到表現優異的Div1選手
  • Rating \(2200 \to 2400\),從表現優異的Div1選手到粉名

另外,在解釋如何練習之前,因為CF用戶很多,其中一些並不知道其他的OJ,所以我想介紹一下其他的在線比賽網站(AtCoder、TopCoder等)。

還有,很高興你們閱讀我的博客。非常感謝CF。

永田正彥

## 2. 常識介紹——一些打比賽的網站

世界上有很多OJ。為了成為粉名,我切了很多OJ上的很多題目。這次,為了 explain the post sections,我想先介紹一些比賽。

2-1. Codeforces [http://codeforces.com/]

Codeforces是世界上最有名的OJ之一,目前有五千多題。

利用CF的最好方式之一是“題目Rating”。例如,1146H Satanic Panic 的Rating是2800,這意味着,如果你的rating大於等於2800,那么你應該在比賽中切掉這個題。

另外,CF分成三個部分(Div1、Div2、Div3)。

再往后,我會使用下面兩種簡稱:

  • Div1A, Div2E等等:代表Div1的A題、Div2的E題。通常,第一題是最簡單的,最后一題是最難的。
  • 難度R2800什么的:“難度R2800”代表這題難度被標成2800。例如,1146G Zoning Restriction 難度R2600,1146A Love "A"難度R600。

2-2. AtCoder [https://atcoder.jp/]

AtCoder是一個“擁有很多好題”的比賽網站。這只是個人意見,但如果你想變強,就要刷AtCoder。

AtCoder有三種類型的比賽:

  • AtCoder Beginner Contest (ABC) : 有4道題。
    • ABC難度一般為R500-R700-R900-R1400。
  • AtCoder Regular Contest (ARC) : 有4道題。通常ARC的前兩題和ABC的后兩題是相同的。
    • ARC難度一般為R900-R1400-R2100-R2600,因比賽而異。
  • AtCoder Grand Contest (AGC) : 有6道題。
    • AGC難度一般是 R1200- R1900- R2200- R2500-R3000-R3300

還有個很方便的網站——AtCoder problems(https://kenkoooo.com/atcoder#/table//)。

在這個網站,你可以看到自己AtCoder的切題列表,知道自己哪些題還沒做,哪些題做了。AC的被標成綠色,嘗試過但沒AC的被標成黃色。

2-3. TopCoder

TopCoder也是一個著名的比賽網站。Single Round Match (SRM) 有兩個部分:

  • Division 2:有三道題,R600-R1300-R2100,被稱為Div2簡單、Div2中等、Div2困難。
  • Division 1:有三道題,R1800-R2400-R3000,被稱為Div1簡單、Div1中等、Div1困難。

我為了到粉名,也用TopCoder訓練。盡管主要是數學題,但都是好題(我尤其喜歡SRM600-699)。

2-4. 這部分的總結

我主要用3個OJ訓練:Codeforces、AtCoder、TopCoder。如果你了解了這3個OJ,就可以去閱讀下一個部分了。在這些比賽網站訓練是很重要也很有效的,而且我覺得這是最快的進步方式。


在第3部分,我會寫很多要點,但都只是我的個人觀點,不信任我也是可以的。很多人遵循我的方法,取得了很大的進步,但也有很多人沒遵循我的方法依然取得很大進步。用我的方法訓練是挺好,但不一定對所有人都有效。


3. 訓練方法介紹

可能有很多人讀過我上一篇教程博客,但現在和兩年前不一樣了。這兩年我有很多遺憾。很多事情我沒做,但我在想,如果我做了,是不是可以進步更快?因此,這篇博客和我之前那篇有很多不同之處。

此外,在rating到達2200前和到達2200后,我的訓練方式完全不同。

還有一件事,這篇博客只是我的個人觀點,訓練方法因人而異,所以我認為你不一定按照我的方法訓練。但我覺得我的方法對一些人來說是最有效的。

如果你理解了這一點,就可以繼續往下讀了。進入正題……3、2、1,走起!

3-1. 訓練技巧 rating 1000~1400

CF上有很多灰名、綠名,他們很想成為青名、藍名,但依然在苦苦掙扎中。

盡管如此,到達青名(1400)只需要做到三點。

  • 能夠快速寫出模擬題(5到10分鍾內)
  • 能夠快速寫出暴力(5到10分鍾內)
  • 能夠在腦子里或草稿紙上把問題分情況討論(例如,N=2、N=3、N>=4)

舉個例子,在Codeforces Round #556中,如果你可以做到以上三點,就可以很驚喜地在Div2中達到200名,這是一個很誇張的例子。但在Codeforces Round #554 (Div. 2)中,你只能達到3400名,rating1250及以下的參賽者可以上分。

平均來說,如果你可以做到以上三點,rating就可以達到1400。

[[如何訓練]]

首先,我建議你打ABC。

盡管CF上有很多好題,但如果你想更容易地練習編程,最好去刷AtCoder。

特別地,我推薦做ABC中的B題和C題。做B題可以學到如何更快地寫模擬和暴力,做C題可以學到如何想題、如何用草稿紙更快地想出解決方案。

從ABC 042開始,出題人加入了英文題面。目前最新的一場是ABC 125,所以共有84場可做的ABC。如果你切了所有的B題和C題,就會學到很多,變得更強。

可以借助AtCoder problems的幫助刷AtCoder,你能從這個網站知道自己做了哪些題。

當你刷AtCoder時,有幾點很重要:

  • 當你想不出解決方案時,應該在思考B題15分鍾、思考C題30分鍾后再看題解。可悲的是,最近幾場ABC沒有英文題解,但你可以讀標程(題解中很可能包含標程的鏈接)。
  • 即使你AC了某道題,在習慣快速寫代碼前,還是可以通過閱讀大佬的源代碼學到一些東西。所以我建議看一些簡單的源代碼。
  • 特別是當你做C題時,我推薦你用草稿紙輔助思考。不用紙的話,用白板打草稿也可以。

我是高中一個計算機社團的社長,有很多社員用這樣的方法獲得了進步。

3-2. 訓練技巧 rating 1400~1900

CF上人數最多的rating區間是[1400, 1500]。他們都很想上分,但從1500開始上分比較困難,很多人放棄了。但也有很多人堅持訓練,成功上分。

要達到1900,需要下面的技巧:

  • 掌握並能夠使用以下主要算法:

    • 暴力
    • 動態規划
    • 深度優先搜索
    • 廣度優先搜索
    • 迪傑斯特拉
    • 樹狀數組
    • 排列數、組合數
    • 乘法逆元
    • 位掩碼
    • 二分查找

    注意:我認為在rating 1800前,線段樹不是必須的。我上紫以后才學的線段樹。

  • 提高手速(例如,R1100的題目5分鍾寫好,R1400的題目10分鍾寫好)。手速在CF很重要,因為一般來說,如果題目難度范圍很大,手速會在很大程度上影響rating。

[[如何訓練]]

如果你不擅長快速寫代碼、快速調試,就應該刷AtCoder。事實上,從統計學上講,很多日本選手手速很快,但不擅長解決難題,我覺得是AtCoder的鍋。

我推薦做ABC的C題和D題。平均來說,如果能在10分鍾內解決C題,在20分鍾內解決D題,你就是手速場中的Div1 😃

如果你不擅長解難度高於R1400的題,就應該學一些上面提到的算法,做做CF上的板題。舉個例子,如果你覺得自己不擅長DP,就刷CF上R1200到R1400的DP標簽的題。讓人驚訝的是,只有約50道難度小於等於R1400的DP標簽的題。

有趣的是,板題都集中在只有Div2的那些比賽中。如果你不擅長只有Div2的比賽,那么很可能是你不擅長使用典型算法,尤其是上面提到的10種算法。

如果你能做板題,但不擅長做難度高於R1500的題,就要開始在TopCoder刷題。這類練習對擅長只有Div2的比賽但不擅長Div1+Div2一體的、分開的比賽的人十分有效。

有時候,尤其是在Div1+Div2的比賽中,一些題目需要數學概念或者思考。因為TopCoder上有很多題用到這些(另外還有簡便的實現!),所以你應該刷TopCoder。

我推薦刷最近100場SRM的Div1簡單。但有些題真的太難了(甚至粉名都切不掉),所以刷之前,你應該看一下題目的通過率。你可以利用https://competitiveprogramming.info/來獲取一些信息。

不幸的是,我不知道有沒有像AtCoder Problems那樣,能夠看自己在TopCoder SRM中做過哪些題的網站。所以,如果你想記錄自己刷過那些題,應該做一個電子表格或者表格。這是我哥哥兩年前使用的電子表格(Sorry for Japanese, but there are no Japanese in Div1Medium page, so you can refer to it沒看懂這句話https://drive.google.com/file/d/1mSy9PM4Km8EVv8Lp4nhitorOe2HbAS1e/view?usp=sharing

當我還是個藍名時,數學思維也很糟糕。在切了50題Div1簡單以后,我在TopCoder成了藍名,在CF成了紫名。

如果你擅長切題,但在比賽中發揮不好,就應該多打虛擬賽。你知道CF的虛擬賽系統嗎?你可以虛擬參賽!

3-3. 訓練技巧 rating 1900~2200

如果你想達到2200,首先,你應該是Div1,並且參加Div1的比賽。這意味着你應該刷很多難題(R1900或更高)。

即使你手速快或者十分擅長切板題,打Div1比賽也是很難的。可悲的是,有很多選手在藍名和紫名之間搖擺

要達到2200,需要以下技巧:

  • 知道並且會用上面提到的10種算法,還要加個線段樹(包括懶標記)
  • 非常快的手速:R1100 5分鍾,R1500 10分鍾,R1800 15分鍾,R2000 40分鍾。
  • 相當好的數學思維和思考問題的能力。
  • 強大的思維,可以支持超過1小時的思考,即使在Div1比賽中途落后了也不放棄。

[[如何訓練]]

這只是我的訓練方式:在rating2000時打了很多虛擬比賽。在這里,虛擬比賽並不意味着“虛擬參與”,而是選擇4到5道難度在自己rating附近的題目(舉個例子,目前rating是2000,那么選擇CF中R2000的題目),並且在2小時內切掉。

你可以利用https://vjudge.net/。在這個網站,你可以從很多OJ上(AtCoder、CF、Hackerrank、Codechef、POJ……)拉題組一場虛擬賽。

如果你在虛擬賽中不能切掉這些題,而且沒有想出解決方案,就應該去谷歌查題解(舉個例子,如果你想找Codeforces Round #556 (Div. 1)的題解,就去谷歌搜“Codeforces Round #556 editorial”)。

在CF上分還有一件重要的事。為了更快的手速,你應該准備一些板子。例如,我認為線段樹板子、懶標記線段樹板子、CRT的板子、FFT的板子、計算幾何板子等等都是很有效的。

3-4. 訓練技巧 rating 2200~2400

這是本博客關於訓練技巧的最后一部分。事實上,我卡在橙名很久了,就連在虛擬賽中,我的平均表現也是橙名。這是因為我之前的訓練方法在橙名遇到了障礙。

Rating 2200到2400事實上非常難——如果你平均表現2200,如果你練習賽打得更多,上粉(到2400)看上去也沒那么難。但是平均表現2400比你想象的要難得多。如果你的rating正好是2400,那么在Div1的比賽上,你一般要打進前20%(例如,如果有525人參加,那么你應該最差在105名)才能上分。

要達到2400,需要以下技巧:

  • Rating達到2200
  • 在Div1比賽中切掉AC少於100人的難題

如果你想切難題和用ad-hoc臨時方法的題,根據TozanSoutherPacks在我上一篇博客下的評論(http://codeforces.com/blog/entry/53341?#comment-373965),“要達到2600分乃至更高,你應該切Boss題,所有這些都是臨時問題或者步驟很多的問題。”我覺得那是對的,但是對我來說,我覺得即使你只想達到2400分,切步驟很多的臨時問題也是有必要的。

[[如何訓練]]

達到2400分最安全的方法是“切4000道題”。我就在TopCoder、AtCoder、CF和一些日本OJ上切了超過4000題。

事實上,有一個傳說(或者說是事實)是,最NB的選手tourist在他這輩子切了一萬多題。

但是可能很多人覺得自己沒時間。所以我會給你一些更高效的途徑。

首先,AtCoder上有很多教育題。我推薦你做ARC尤其是ARC058到ARC090的E題和F題(尤其是AtCoder中700到900點的題目)。盡管以前的ARC在“思維”和“模板”之間是平衡的,但可悲的是,我認為AGC和最近的ARC實際上太偏向思維了,所以如果你的目標是在CF上分,我不推薦它們(盡管如果你想達到2600乃至更高,還是要刷AGC)。

對我來說,實際上,刷了ARC以后,我在CF虛擬賽的平均表現從2100提高到了2300(I could not reach 2400 because start was early)。

如果你切不動題,我推薦你放棄思考並且看題解的時間如下:

AtCoder點值 CF難度 思考時間
600 R2000 40分鍾
700 R2200 50分鍾
800 R2400 60分鍾
900 R2600 70分鍾
1000 R2800 80分鍾

如果你切了AtCoder上的教育題,你編程比賽的技能將會有所提高。但還有另一個問題,沒有付諸實踐,你沒辦法上分。

所以,你應該至少在CF上打50場虛擬賽(尤其是Div1)。在虛擬賽中,你可以學到,紫名、橙名應該如何打比賽(比如比賽策略),以及如何在CF比賽中利用在AtCoder學到的技巧。我強烈推薦在虛擬賽后看看所有題的題解,除了太難的題(比如在比賽中AC人數少於30的題)。我還建議,在打完比賽看完題解后在筆記本上寫一些對於比賽策略、教訓和可以改進的地方的反思。

此外,我建議你每周一次,花點時間思考一些難題(比如CF上R2800的題)。如果你想了很久也想不出來,我建議你去讀題解,因為那樣你可以學到很多。解決難題可能會給你一場上分100+的機會,也會給你更快解決簡單題的機會。

最后,我猜這個方法對於超過30%的人奏效,因為我用這個方法在CF上粉,我的孿生兄弟square1001用這個方法在TopCoder上紅。希望我的方法可以產生新的粉名:)

4.訓練心理

心理問題是選手中最常見的問題之一。即使對我,直到最近兩個月前,出於對一場掉分100+的恐懼,我超過9個月沒打過CF上rated的比賽。另外,還有幾場比賽我甚至都做不到看下一個題,因為我做不出來更簡單的題,心態崩了。

我最近發現一種鍛煉心態的辦法。

  • 制定一個比賽前的常規程序。這能讓我們在比賽期間集中注意力。
    • 事實上,就我而言,我的常規程序是在比賽快開始時看着倒計時減少到0。黑紅大佬yutaka1999實際上在IOI開始前就在修禪。
  • 如果你比賽中沒發揮好(比如20分鍾內切不掉B題),不去看榜也是個好主意。
  • 還有一件重要的事:“比賽過程中不要管rating”。
    • 我覺得,即使這場要掉分,下一場上分的可能性也提高了。這就是為什么我在比賽過程中不管rating。
  • 不要過於在意之前犯過的錯誤。錯誤也是一次好的學習機會,每個人都會犯錯。即使是tourist也曾經在AtCoder World Tour Finals上翻車。
    • 我覺得吧,“rating”和“你犯過多少錯、做過多少反思”之間存在關聯。

以上這些方法不僅在正式比賽中適用,還在虛擬賽中適用。注意:比賽中不要有太大的壓力,開心就好!

5. 虛擬賽推薦

在寫關於虛擬賽的建議之前,我認為虛擬賽有以下兩種類型:

  • 虛擬參與:選擇一場比賽,就像真實參賽那樣做題。和CF的虛擬賽系統一樣。
  • 虛擬比賽:使用VJ或者其他的評測系統。從CF上挑幾題難度在自己rating附近的題,並在2到3小時內解決它們。

首先,以上這兩種方式我都推薦。

對於虛擬參與,我覺得你可以學到比賽策略、心態和其他一些比賽技巧。對於虛擬比賽,我覺得你可以集中精力卡一道題,因此解題、復習效率會得到提高。

這就是為什么當我在刷CF上的難題時,總是用VJ進行虛擬比賽。

如果你想在AtCoder打虛擬賽,用https://not-522.appspot.com/(遺憾的是這個網站是日文的,如果你不是日本人,只好委屈你用一下谷歌翻譯了。。。)。

6. 未來願景

幸運的是,在2019年4月29日,我CF的rating達到了2585,非常接近紅名了。我很高興,也真的很感激CF管理員和CF社區。

我實際上已經定下了未來的目標:黑紅!

實際上,我最近在CF打了很多比賽或者虛擬賽。我在CF上最近10場比賽的表現是: 2865, 2661, 3029, 2890, 2858, 2875, 2318, 2717, 2506, 2891(平均2761.0)。

所以,我大概還差250分到達黑紅。我為了實現夢想正在做的努力如下:

[[如何訓練]]

  • 幾乎每天都打2到3小時虛擬賽。賽后看題解、看黑紅大佬的代碼,寫一個小時反思。
  • 有時候(大約一周一次)從CF上選大概5題左右(難度從R2200到R2800),在2到4小時內解決。
  • 即使打比賽三年了,我還是覺得有很多黑科技(實際上和算法板子不同)是我不知道的。所以比賽中如果有超過20人做出來的題目我沒做出來,我就會去看題解。
    • 我覺得,如果我能在比賽中把幾乎所有20個AC以上的題目做出來,早就是黑紅了。

7. 總結

這就是我要給CF社區說的所有訓練方法。真心感謝你的閱讀。

我使用CF很久了,也在社區中得到了成長。所以,我想我應該給CF社區做點什么貢獻。做貢獻有很多方式,我選擇講述在CF上分的實用技巧。我認為這是給CF做有實際意義貢獻的最好方式之一。

最后,我建議一步步用一定的訓練方法提高你打比賽的能力。但是訓練方法因人而異,我不覺得我的方法總是最高效的,同樣,我也不認為你必須按照的我方法訓練。

但我覺得,這對某些人來說是最高效的方法。希望這篇博客有用,即使只有一小點兒。

因為我只是日本的一個高二學生,文中可能有很多語法錯誤,我英語也確實不好。我必須表示歉意,但相反,我必須感謝讀者。謝謝你的閱讀。

最后,祝你好運,祝你在CF上分,祝你在程序設計競賽玩得開心。這就是我這篇博客的總結。再次感謝。

永田正彥

graph TD 1600-->|訓練|1900 1900-->|訓練|2100 2100-->|訓練|2200 2200-->|訓練|2400


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM