【比賽記錄】2021年4月 ICPC昆明站


退役記

整個XCPC,從2017年10月買了第一本書《挑戰程序設計競賽》開始,一直學到參加2021年4月ICPC昆明站為止,歷時3.5年的超長XCPC生涯終於結束了。整個大學生活除了XCPC真的幾乎什么都不剩下了(可能唯一是2020年6月到9月摸魚去騰訊參加了一段實習吧)。在退役的一場拿到了第一個也是最后一個金獎,還是金獎的倒數第一名,還是去掉打星隊伍后的金獎的倒數第一名,能說什么呢,真的只是幸運吧。

從選賽站開始說吧,隊友們都想去線下參加,我不太贊成線下因為我覺得到時候可能搞核酸隔離什么的就麻煩死了,事實證明線下推遲得太厲害直接等到現在疫苗都普及了。一開始考慮去不去澳門,雖然有港澳通行證但是怕境外真的要核酸隔離什么的,而且時間太趕了(沒想到推遲到比昆明還后),就選了昆明。出了報名表之后看見很多強隊,就有點慌了,仔細一個一個查強隊們的歷史戰績,肉眼可見比我們強一截以上的大概有接近50隊,當時都已經無所謂了,戰勝20個強隊拿金牌什么的,我已經不指望了。

不過后面我們隊伍每星期的三四六日都會開一場4小時的XCPC來練習配合,逐漸的大家很默契,在很多個賽區的錄像里(在不小心看了賽后榜和聽了賽后討論關鍵字的情況下)拿了銀牌金牌,覺得希望是逐漸提升的,但是具體提升是多少實在不清楚。聯想起wls等使用CF分對區域賽成績進行的估計,CF2000分對應金牌實力,仔細算了一下我們是2047分,也真的有金牌實力。回想起南京卡的那個樹上背包,后來在div1的C見過,是個2400分難度的題,那么我感覺可以估計金牌題就是2400分難度,所以平均分是2047分的科技互不相同的三個人,在時間延長3小時並且配合默契的情況下搭配着打出2400分的題,是不是就是這個理論的來源呢?

最后證明這個理論可能是正確的,J題和M題都是要大家配合着通過的:J題M大佬和Q大佬一起從多個角度理解構造,然后一起檢查代碼是否實現有問題(沒錯我們真的有code review),還assert了一發確認代碼實現沒有錯(意思就是算法錯了),雖然后面數組開小了發生段錯誤(牛客網OJ居然會提示RE的種類?!)罰了20分鍾,那時候可能心急了,還好全場只有那一次的小dirt,相比其他人的超過dirt次數我們最后真的就靠6分鍾的罰時優勢勝出;M題是q大佬推了很久的區間前綴和作差,然后指出是離散化后兩棵對應區間的權值線段樹的差值,然后在這個差值上面找不超過x的數的前綴和,然后他翻了翻板子發現他的主席樹沒有離散化的!我想了下好像比賽前一天晚上沒睡着看了看2019年去徐州站的時候帶的板子,里面有我親手擼的全功能主席樹!打開兩年前的東西一看發現兩年前的自己已經幫現在的自己離散化好了,建立主席樹的整個流程也有詳細的中文+代碼的示意,還提供了全功能主席樹的各種版本的實現指導!12分鍾敲完整個主席樹然后套上Q大佬推出的詢問公式,再對一對樣例,總共花了18分鍾就過了這個卡了4個小時的M題!這就是傳說中的“現在的你一定會感謝兩年前努力的自己”嗎?!作為一個兩年沒有見過杜教篩和主席樹的人,新的模板里面都直接跳過了這倆了,沒想到這一場退役站都出了,真的是不知道說什么了。

回過頭說一下I題和K題吧:

I題是計算幾何擔當M大佬完全一個人單推的,另外兩個人題目都沒看,然后就1A了,學了幾年的計算幾何在關鍵時刻終於依靠快速實現和0dirt爭取到罰時優勢拿到金牌,M大佬應該很開心!

K題是個麻將題,最后看榜發現真的很多隊伍都不會打麻將,就像我們隊伍不會這個主席樹一樣。我們的實現就是枚舉舍棄的牌和新加入的牌,然后dfs去check是否和牌,中間加入了一堆亂七八糟的剪枝並且這些剪枝一度把正確答案給剪掉了!我感覺這題確實是不好搞的,要有比較豐富的代碼實現功底(卡常經驗)和比較豐富的dfs經驗。

第一件事就是搜索的時候狀態的設計,這里是傳統的用cnt[x][y]表示第x種花色的第y張牌的數量,放在全局數組里面進棧入棧時修改。然后搜索的應該是“每張牌去組合出什么牌型”而不是“由哪些牌型組合以及這個牌序由哪些牌組合”,這個假如第一步就錯了應該就會寫得很憋屈吧。然后就是要記錄是否當前已經用過了雀頭,否則就會搜索出AABBCCDDEEFFGG這種七對子,或者更離譜的AABBCCDDEEEFFF這種什么牌型都不是的組合。

然后就是要考慮怎么減少dfs的重復搜索問題,一種思路是對牌型狀態進行hash,記錄某種牌型是否是和牌牌型,這個我寫了一下我就放棄了(好像清華是這樣寫的)。我改成枚舉每一張牌參與的牌型是什么,也就是說假如這一張牌 \((x,y)\) 參與組成 \(a\) 個雀頭 \(b\) 個刻子 \(c\) 個順子,一張牌組成順子是指它作為順子的最小的那張牌出現,那么需要滿足下面的條件:

1、若 \(a==1\) ,則現在dfs的狀態中,必須沒有雀頭,否則就有兩個雀頭了,是非法狀態直接跳過。
2、 \(2a+3b+c==cnt[x][y]\) ,也就是恰好等於這張牌的所有出現次數,立刻在這一層就把這張牌的所有出現次數用完,這樣以后就再也不會搜索等價的牌的狀態了,這樣避免了你搜索我我搜索你。
3、 \(cnt[x][y+1] \geq c, cnt[x][y+1] \geq c\) ,也就是這張牌真的能組成 \(c\) 個順子,把后面的連續兩張牌也用掉。

除此之外要注意,字牌是不能組成順子的,還好打過日本麻將,不然看半天都不知道錯哪。

第二種剪枝是:check成功之后要及時返回,因為這里只問是不是和牌,沒有問和什么牌型,這里寫成“在這一層及時返回”就比“在上一層不進入下一步搜索”要簡單。

第三種剪枝是:可行性剪枝,每種花色的牌,也就是 \(cnt[x]\) ,都必須是 \(3k\) 或者 \(3k+2\) 的數量,並且為 \(3k+2\) 的花色必須只有恰好一種。這是一個超級大的剪枝,因為后面搜索立直之后聽什么牌的情況,調用dfs前是隨便枚舉一張牌的話,大概率連花色內部的數量都湊不全。這個剪枝應該可以在暴力枚舉“進張”的時候剪除掉90%的dfs搜索樹,是真的直接從樹根一刀剪掉了,是不是應該改叫“剪根”呢?

第四種剪枝是:重復枚舉剪枝,這個是要在調用dfs前進行的,方法是給手上的牌排個序,然后枚舉打出某一張牌的時候,若前一張牌和現在的牌一樣,則說明已經枚舉過了,直接跳過這張牌的枚舉。

第五種可能的“優化”是:優先搜索字牌,因為字牌的牌型是固定的,只能有3k+2這種組合,假如是先搜索別的最后搜索字牌,這個步驟會重復在dfs的每個葉子出現,這樣子調整搜索順序會讓搜索樹的葉子消耗更多,但是枝干分叉更少,這個“優化”可能會是負優化。

這次比賽只用了前四種剪枝,從結果上看還好沒寫第五種,要不可能罰時就失去了那6分鍾的優勢了。

2021昆明 - 華南理工大學_單推聖人惠

寫完M題的時候還有30分鍾,手里還有一個不知道15怎么用的C題,實在已經假得放棄希望了。相當於掛機到結束看封榜了,看見最后是38名當時覺得挺失落的吧,因為感覺打星隊伍不會有這么多在前面,M大佬執意要拿打星隊伍名單數一數,發現前面打星的人剛好是3個,真的就正式隊伍第35名最后一個金牌唄?不過我學了3年的數學,最后真的和自己預測的一樣,幾乎沒有機會用上了,因為需要用數學的題可能已經是穩金之后了。2019年的徐州站和2020年CCPC的網絡賽應該是我參加的正式賽里面唯一用到數學的吧。


流水賬

H簽到題,打好文件發現過了400個人,哇真滴nb,CF都不敢這么搞。沒啥好說的,不過想diss一下那個10秒過題的。

L簽到題,一開始q大佬就開了這個,我覺得還挺難的,后來覺得應該不要從圖的角度考慮,直接貪度數,結果也是不對,突然意識到是不是每有一次下降就要開一種新的顏色(雖然也是錯的)。后面還是直接歸納了,放a[i]的時候前面有j<i且a[j]>a[i]的,這些顏色都會和ai連邊,所以每種顏色只需要保存最大值,這個就線段樹或者樹狀數組維護一下后綴和就行。

I題,計算幾何,m大佬偷偷1A的,都沒來得及看。

然后開J題,並行排序,每次可以交換兩個位置,問最少交換幾次。一開始m大佬搞個每次每個環siz減半的,看起來很對,然后交上去掛了。

與此同時,一車人過了M,但是我們死活不知道M是干嘛的,還在想是不是不強制在線的話搞個莫隊,或者弄個奇怪數據結構維護前面連續可取的一段和后面的一堆離散的點,但離散的點總是O(n)個,實在沒想到怎么做。

搞不懂為什么全世界都會M,想着可能我們陷入坑里了。換題,我去搞K,打麻將。q大佬說這個麻將讓我寫,很快就行。hhh事實上我寫了很久。

K很快可以dfscheck到自摸,用的各種奇丑的dfs,這時q大佬告訴我這套麻將可以有無窮張同樣的牌,我這個就應該不對了,而且不知道怎么check立直,想了想直接暴力枚舉換掉哪張然后調用上面的自摸就行了。

m大佬說想交一發assert看看是哪里錯了,我其實是不太想的,可能我當時覺得J還是有機會的吧。

又過了一段時間,K的立直搞出來了,不過一直多了幾種答案,打印出來看看。這時m大佬就交一發assert給J,WA了,這時說明J是算法問題不是實現問題,從結果來看這20分鍾是完全值得的。

我想好之后,給K換了枚舉刻子數量和順子數量的方法,然后給搞了幾個陰間剪枝,想着要不交上去試試吧。這時J題m大佬和q大佬也大呼“只需要操作兩次”,反正沒聽懂,頭一直暈暈的,他們交上去段錯誤了,居然!居然開小了!改了之后就過了。

我的陰間剪枝跑得飛快,K在J的2分鍾之后就過了。

然后自閉的時間就開始了,期間去看了看C,覺得是個區間DP,想假了復雜度上去連T兩發,是真的沒睡醒。

然后往往復復不知道是看C還是看D,都不知道他們咋搞的,以為D是南京H的復現,上去演了一發,算咯。

在4小時封榜之后,准確說是15:07,q大佬突然意識到M這個東西可以用前綴和對應節點作差,然后求一段區間和加上去模擬。然后這個東西看起來就很主席樹,這時候讓q大佬去上機,我和m大佬看看有什么細節。不過q大佬的主席樹沒有離散化,就下來了,我突然想到昨晚我記得我兩年前的板子里面有我的碼農心血,找出來的時候是15:12,然后一路手速爆抄,再調了7分鍾,在15:30的時候提交了一發1A。

然后其實當時就有點不太想繼續做了,就開始裝模作樣的給C題反復交假算法,哈哈哈。挺有意思的吧,假如當時去看G可能30分鍾可以?但是作為工具人的我已經很疲倦了,沒有人能寫了,我覺得還是放棄吧。

封榜出來38名,當時覺得有點可惜,m大佬非要去數數前面有多少個打星的,我覺得哪有這么多金牌打星隊啊,算了吧。結果一看真的有剛好3個,我們就最后一個金牌的位置。


免責聲明!

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



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