1. 程式人生 > 其它 >【題解】CF1580 題解

【題解】CF1580 題解

賽時通過 ABCD

A

列舉上下邊界,從左到右掃描右端點維護左端點答案,顯然推進一格右端點對所有左端點的影響是一樣的。

程式碼:Submission #133205897 - Codeforces

B

笛卡爾樹 dp 。複雜度是 \(O(n^5)\) 。稍微剪點枝,用一些滿二叉樹葉子個數的限制之類的東西可以做到很小的常數。

程式碼:Submission #133207689 - Codeforces

C

根號分治。大的直接修改,區間加減可以分塊 \(O(1)\) 做單次(詢問只有 \(m\) 次,複雜度均攤一下)。小的按照長度分類,按照餘數討論貢獻即可。

程式碼:Submission #133206742 - Codeforces

D

笛卡爾樹 dp 。跟普通樹形揹包一樣的複雜度分析方法,時間複雜度 \(O(n^2)\)

程式碼:Submission #133207132 - Codeforces

E

F

很神的題,這裡寫一下大致思路。

討論 \(m\) 是偶數,\(n\) 是奇數的情況。注意到相鄰的兩個數最多有一個不小於 \(\frac{m}{2}\),那麼在所有的相鄰兩數都小於 \(\frac{m}{2}\) 的位置將原序列分割為若干段,每一段內兩種數交錯,且每一段長度均為奇數。

考慮在每一段內,將所有不小於 \(\frac{m}{2}\) 的數減去 \(\frac{m}{2}\),此時這個數的取值區間為 \([0,\frac{m}{2})\)

,與其他數無異。那麼這樣的話求這一段的方案數其實就是做原問題的子問題,遞迴處理子問題,令 \(F_{m'}(x)\) 表示 \(m=m'\) 時的答案。

接著就是考慮合併。首先就是當前問題的合併。假裝第一個數和最後一個數都小於 \(\frac{m}{2}\),列舉第一段的長度計算起點的方案數,後面段的拼接方式很容易求得。

接著就是往上合併,此時我們不需要考慮首尾是否合法。那麼最後的序列一定形如:首尾都是偶數段,中間若干奇數段的形式。這個直接卷積就行。注意還需要額外考慮一種情況:如果整個序列長為奇數,那麼可能出現首尾都不小於 \(\frac{m}{2}\) 的情況(中間交替)。

這樣的話時間複雜度為 \(O(n\log n\log m)\)

接著就是 \(n\) 是偶數的情況,注意到因為整個序列交替是合法的,所以考慮答案的時候額外考慮一下就行(記錄 \(ans_1,ans_2\) 分別表示是否完全交替的合法方案數即可)。

最後考慮一下遞迴時 \(m\) 是奇數的情況:有一些小問題在於,將不小於 \(\lceil\frac{m}{2}\rceil\) 的數減去 \(\lceil\frac{m}{2}\rceil\) 後,該數的取值區間和沒被減的數不一樣,這樣就不是子問題了。

同樣考慮一個段,交替出現的是不小於 \(\lceil\frac{m}{2}\rceil\) 的數和小於 \(\lceil\frac{m}{2}\rceil-1\) 的數,此時將不小於 \(\lceil\frac{m}{2}\rceil\) 的數減去 \(\lceil\frac{m}{2}\rceil\) 可以發現取值區間一樣了,直接計算方案數就行。剩下的能取到 \(\lceil\frac{m}{2}\rceil\) 的數只有長度為 \(1\) 的段,額外考慮一下即可。

程式碼:Submission #133226888 - Codeforces