Codeforces Global Round 11 A-F題解

很久以前,我在退役之後說過要在Codeforces上與你們再見。我回來了。

先寫A-E的題解,F和G之後補。先寫一部分可以防止咕咕咕。

F已經補上,G的題解非常妙,我將單獨開一篇來介紹。

A. Avoiding Zero

重排一列數使得前綴和始終不爲\(0\),可能無解。

題解:和爲\(0\)則顯然無解,否則考慮分爲正數和負數兩部分,將和的絕對值大的那一部分放在前面,就不會出現前綴和爲\(0\)了。

B. Chess Cheater

你有自己\(n\)場比賽的結果(贏或輸),輸的場不扣分,贏的場得一分,如果上一場也贏再得一分。你可以修改\(k\)場比賽的結果,使得自己總分最大。

題解:顯然只需要把輸改爲贏。那麼修改完之後贏的場次就是\(\min\{cnt+k,n\}\),其中\(cnt\)爲本來就贏得的場次。

然後只需要最小化連贏的場的段數。可以通過把兩段連贏之間的輸改成贏來減少一段。那麼只要按照連贏段之間的距離升序排序儘量消除就可以了。

C. The Hard Work of Paparazzi

有一個二維平面,從一點\((x_1,y_1)\)走到另一點\((x_2,y_2)\)所花的時間爲\(|x_1-x_2|+|y_1-y_2|\)。有\(n\)個事件,第\(i\)個在時刻\(t_i\)在點\((x_i,y_i)\)發生。你時刻\(0\)\((1,1)\),問最多參與多少事件。事件發生時刻嚴格遞增。\(|x_i|,|y_i|\leq 500,n\leq 10^5\)

題解:比賽時居然沒想到...老了老了。考慮樸素\(dp\)\(f_i\)表示參與\(i\)號事件時之前最多參與了幾個事件。普通的一次轉移是\(O(n)\)的,但考慮如果時間差大於\(2*|x|\)就肯定能到了,因此前面最多隻有\(O(|x|)\)個事件是需要逐一判斷的。複雜度優化爲\(O(n|x|)\)

D. Unshuffling a Deck

你有一個長度爲\(n\)的排列\(p\),每次可以將其分割爲若干段,段內順序不變,所有段之間順序反轉。給出不多於\(n\)次這樣的操作將原排列排序。

題解:記錄\(k\)是排列中的第\(a_k\)個。如果對\(k=1,2,\dots,n-1\),都有\(a_k<a_{k+1}\)就排完了。否則找到某一個\(a_k>a_{k+1}\)\(k\)

\(k+1\)之後連續遞增的一段爲\([a_{k+1},pos]\)(即這個區間內\(p_i=i-a_{k+1}+k+1\)),將排列分割爲\([1,a_{k+1}-1],[a_{k+1},pos],[pos+1,a_k],[a_k+1,n]\)四段,用題中操作,操作完畢後\(a_k+1=a_{k+1}\),即\(k\)\(k+1\)連在了一起,同時不會破壞任何已經連在一起的對。不斷重複上述操作即可。

E. Xum

黑板上初始有一個奇數,每次可以選黑板上兩個數(可重複),再寫出它們的和或異或和,重複若干步寫出\(1\)。限制比較寬鬆。

題解:我的做法是非標準的做法。考慮用線性基判定是否可以通過異或得到\(1\),先加和幾次自身擴充一下線性基,之後每次隨機從線性基中得到兩個數取和加入,不久就會出解。對於\(2^k+1\)的情況會比較苛刻,要先得到較大的倍數加入線性基中。

F. Boring Card Game

桌上有\(1,2,\dots,6n\)標號的\(6n\)張連續牌,Alice和Bob玩遊戲輪流取\(3\)張,Alice先取,每次取出位置連續的三張牌並將上下兩堆牌合併。給出Alice最終拿到的所有牌的標號,復原一種可能的遊戲過程,保證有解。\(n\leq 200\)

題解:

先考慮問題的弱化版:取消輪流取的限制,允許某人反覆取三張牌,先判斷這個條件下是否有解。

那麼考慮一個貪心:從左到右掃描牌,逐一加入棧中,如果加入後棧頂出現三張屬於同一個人的牌,就視爲進行了一次取走操作,將這三張牌彈出。

如果貪心算法最終能將棧清空,顯然就得到了一組合法解。現在來進一步證明如果弱化版問題有合法解那麼棧一定被清空。

對取牌輪數\(n\)用數學歸納法。
\(n=0\)時顯然成立。
假設\(n=k\)時成立。\(n=k+1\)時,對某種有解的情況,我們隨意考慮它的某一個解,這個解的第一步取走的必定是標號連續的牌,設爲\(k,k+1,k+2\)。如果我們先打破貪心規則取走這三張牌,由數學歸納法,剩下的牌可以通過貪心構造一個解。
進一步轉化,可以發現如果將之後的若干不依賴於\(k,k+1,k+2\)三張牌被取走的前提就能取走的牌先於\(k,k+1,k+2\)被取走,也是合法的。因此我們換一種打破規則的方式,改成在\(k,k+1,k+2\)中的一些牌置於棧頂並可以取走時,如果並非\(k,k+1,k+2\)這一組合就不取走,直到\(k,k+1,k+2\)都出現在棧頂才取走它們(此時棧頂可能有\(4-5\)張屬於同一人的牌),也能在之後合乎貪心的過程給出一個解。
最後,由於\(k,k+1,k+2\)是連續的,假設我們保留了本來可以取走的\(a,b,k\)不取走,\(k+1,k+2\)必定馬上到來並將\(k\)帶走,此時棧頂留下\(a,b\),但是如果我們合乎規則操作,直接取走\(a,b,k\),棧頂就剩下\(k+1,k+2\),由於這些牌的歸屬者相同,對於之後的過程來說,除了標號\(k+1,k+2\)\(a,b\)沒有本質區別,因此原來能得出解此刻仍然可以得出解。\(a,k,k+1\)的情況也是類似的。而此時是完全符合貪心規則的。因此也就證明完畢了。

因此原問題有解的必要條件是棧能夠清空,也就是得出一種弱化版的方案,現在再來分析一下該方案中每一組牌之間的依賴關係。可以得知,如果我們讓三張牌對應到包含這三張牌編號的最小區間,那麼任何兩個區間之間只有無交和包含兩種關係,因此可以建立一個森林,樹中祖先的區間包含所有後代的區間。對於這三張牌,顯然只有其子樹對應的三張牌組取完纔可以取。不難發現,對一組三張牌,儘管其後代中可能存在歸屬者相同的牌組,但由貪心的性質其兒子對應的歸屬者都是與自己的不同的。

重新考慮輪流取的限制,我們對森林的操作就變成了:只有所有葉子都已經被取走的節點可以被取走,且必須\(Alice\)的牌的點和\(Bob\)的牌的點輪流取走。考慮是否存在這樣一個取走的序列。

首先,最後一組取走的牌一定是森林中某棵樹的根。因此,如果所有根都是\(Alice\)的牌,就一定無解。那麼下面只要說明森林裏有一棵樹的根屬於\(Bob\),就一定能找到一組解。

要取\(Alice\)的節點時,假設沒有\(Alice\)的節點作葉子,那麼所有\(Alice\)和某個兒子\(Bob\)節點配對。但是\(Bob\)節點至少有一個根,不滿足條件,因此有\(Alice\)葉子節點,隨意取一個即可。

而要取\(Bob\)的節點時,此時\(Bob\)的節點多一個。分兩種情況:\(Bob\)的根只有一個和有多個。
如果有多個,假設沒有\(Bob\)葉子,就令每個\(Bob\)點和某兒子\(Alice\)點配對,而\(Alice\)點少一個,必不可行。又由於\(Bob\)根多於一個,取走一個並不影響“存在至少一個\(Bob\)根”這一性質,因此隨便取。
如果只有一個,那麼再分類:
如果這個點有兒子,本來就不可取,直接利用結論隨便取走一個葉子即可。
如果這個點沒有兒子,且除了它以外沒有別的樹,它就是最後一個點,顯然可以取走。如果沒有兒子且還有別的樹,一定是以\(Alice\)爲根,不考慮這個點後的討論和\(Alice\)相似,一定可以找到另一個\(Bob\)葉子。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章