Codeforces練習筆記2

2022-09-09 13:39:18 字數 2939 閱讀 9030

不難發現,對於乙個聯通塊內的點,顯然是\(b\)權值越大的在越前,而且整體而言能向前則向前

對於乙個點加入到乙個聯通塊中,只要查詢聯通塊內有幾個點的權值大於(小於)它,對應的加加減減即可

問題是加入乙個點時可能聯通兩個聯通塊,這就很痛苦了。

這種塊塊的合併多數使用線段樹合併進行維護,有點類似於\(pkuwc\)的\(minnimax\),通過線段樹合併維護\(dp\)陣列

注意原序列似乎沒有任何性質,最多判個\(-1\),末序列的的性質顯然要多很多

最直觀的,最後如果有一列是單調不減的,那麼顯然最後一次操作必然是這一列,若有多列,可以發現是等價的

然後繼續倒推一次,倒數第二操作的列在單調遞增的列按照權值分段後,每一段也是單調不減的。

發現這樣一直倒推就可以推出來可能的操作序列。

然後正序模擬一次,在\(check\)一發,就可以判斷了,而且也符合運算元的限制

顯然要盡可能的叫便宜的朋友帶水,於是先按照b進行排序

然後列舉朋友,可以通過資料結構維護當前這一時間的水量有多少和在不多餘的情況下最多加多少水。

然後盡可能多買水即可

第一反應就是設乙個\(string\)型別的\(dp\)陣列,這樣處理轉移非常方便。

由於存在r操作,會對後續dp時加入字元的權值進行修改,這使得dp較難進行

所以不妨把這些東西記錄到\(dp\)陣列內,\(dp[i][0/1]\)表示處理到i,最後一次操作是否為r所能得到的最小字典序的字串

這樣就處理了改變後續字元的問題。

不妨先考慮一下拆數貪心策略。

對於乙個不大於\(2^x\)的數,每次拆數會使不大於\(2^x\)的數的個數增加\(1\),這顯然一種平凡情況

對於乙個大於\(2^x\)的數,設之為\(2^k\),將其分解為\(2^\)個\(2^x\)的數需要\(2^-1\)次操作,顯然比上一部分要更加優秀

同時,如果不完全分解,則不優於第一種操作。

然後程式的大致流程就出來了。

先進行第二種操作在不超過個數的情況下盡可能多的完全分解數。

如果此時僅進行操作一即可完成,則進行操作一。

否則第二種操作部分分解使得可以只進行操作1完成,這可以直接倒推得到。

首先有個基本結論:%%chasedeath

沒想到有一天會在自己的部落格裡安利別人的部落格

然後考慮分配過程:

對於\(n\equiv 0 (mod 3)\),對於原有的置換環,12優先配對,剩下自己配

對於\(n\equiv 1(mod 3)\),先取出2(由2環或者2個1環得到)剩下進行上一步操作

對於\(n\equiv 2(mod 3)\),同樣先特判4或者2個2,剩下按照第一步處理

羨慕人家紮實的數學功底

見博主的另一篇博文

對於不存在答案的情況,顯然是存在乙個分叉導致岔路的3個(或以上)支路無法和諧的染色方案

然後可以拓展結論:若樹的直徑大於等於\(k\),且不為鏈,則必無解。

證明:由於直徑上有分支,分別考慮該分支在直徑兩側的限制不難發現必然矛盾

對於鏈的情況顯然很好構造,對於直徑小於\(k\)的情況,相當於沒有限制

首先不考慮\(shift\)操作,顯然原圖有解當且僅當原圖存在尤拉通路。

於是現在考慮\(shift\)操作後的有解的圖的特徵,這裡僅不考慮存在尤拉通路的圖。

首先,這個圖中不存在環。若存在環,則在遍歷是必然會增添不聯通的塊,除非存在尤拉通路

設此時第一步走的邊為\(u->v\),則在之後的遍歷中必然要回到\(u\)或\(v\)來刪除這條邊

由於\(v\)再走一步的邊會被刪除,所以回到\(v\)的路徑必然是個環,不合法。

所以\(v\)只能回到\(u\),但是如果不直接回到u,這樣又需要環才能實現,也不合法。

所以\(v\)只能直接返回\(u\)。

該策略只能解決菊花圖

然後問題就簡單了:給定乙個圖,查詢其能否視為乙個菊花圖,和乙個尤拉通路的乙個端點為菊花圖中心的圖的結合。

顯然全圖的核心在與菊花圖中心,考慮列舉。

由於尤拉通路的一端為菊花圖中心,所以菊花圖的"葉子"不能存在於尤拉通路的子圖中。

同時核心的非"菊花圖葉子"分支不可能由shift操作後的路徑解決,必然存在於尤拉通路的子圖中。

有了這些結論,**就比較好寫了

這也能是個構造環的題?!沒想到鏡子是單面鏡

先特判掉不需要鏡子的情況。

注意到對於\(a_i=j\),我們可以在i,j分別放一面鏡子使其到達,但是相應的會影響\(j\)的到達情況.

設\(b_i\)為\(i\)號發射器對應的鏡子的行數,\(i\)不會對\(a_i\)造成影響當且僅當\(b_i\)>\(b_\)

建立圖的模型,將\(i\)向\(a_i\)連一條邊,得到的圖就是每個點都有一條出邊,每個點都有一條入邊的多個簡單環

顯然僅靠環內的點不可能滿足整個環,而且只要拋棄乙個點就可以滿足整個環。

最後,還注意到拋棄的點可以重複使用。

見博主的另一篇博文

若乙個人選擇了存信,那麼當另乙個人寄信時必然選擇存信。

證明:一旦r處有信時,之後r處始終有信(只不過是交換了兩人的信而已)

每一封信都會經過一些"轉手",到達\(t_\)。

構建模型後其實就是一顆樹,貢獻就是樹邊的權值和,"轉手"操作實際上是使樹邊提前合併,使得可以減少一些樹邊的貢獻,這個操作至少是不劣的

於是可以構建出樹,注意到每顆子樹向上傳遞的只有一封信,使得狀態數非常少

同時注意到這顆樹還按照奇偶分層,分別對應兩個人,樹形\(dp\)就很好寫了

重要的思考方向:將對樹的操作轉為對直徑的操作

先不考慮灰色點。

對於聯通的相同顏色點,顯然可以一起操作,所以我們先將原樹縮點。

原樹縮點後成了一顆黑白點相間的樹。

對於其直徑,其最優的刪除的方式之一為從直徑兩端取相同顏色的點進行刪除。

再刪除直徑時可以順便處理掉非直徑的節點。

灰色可以在任意當做黑色點和白色點,所以對答案實際並無影響,求直徑時也不需要將其計入長度。

Codeforces 練習記錄

標籤裡的 dp 是騙人的,根本沒有 dp 主要思維難度在於乙個轉化,題面開始看上去很嚇人,選取轉化題意就是給定乙個序列,每次可以選取兩個相同的數,在兩者之間選取任意個數消去,問最多能消去多少數。第一想法,選取到兩個數後將之間的所有數都消去會比較優,事實上確實如此,但是如果消去的數之後能與別的數組成區...

codeforces 1114F 線段樹練習

這是一道用線段樹維區間值的一道題,題意很簡單,就是對於給定的乙個序列,初始時每個數的值不大於300,然後有兩中操作,乙個是對區間 l,r 的每個數乘上以個數x,乙個是詢問區間的乘積的尤拉函式值,首先對於第乙個操作顯然可以用線段樹的延遲更新來完成,對於第二個操作,我最先沒考慮資料,就想著直接維護區間的...

CodeForces 2A(簡單模擬 map)

原題目位址 本題問最後誰贏,假如最終得分相同的話 為m 獲勝者就是 最終得分為m人中 先得到m分的人 3個for並列 第乙個for,算出每個人的最終得分。輸入輸據的for,即預處理操作 第二個for,算出最高得分m。第三個for,把最後是高得分m的幾個人之中,看他們誰的score先達到 m,之後輸出...