SDOI2019 Round2

這鬼傢伙已經咕了很久了……數組

SDOIR2的題目挺好玩的~函數

快速查詢(???)

不難發現全部的操做均可以經過區間打Tag實現優化

那麼能夠維護兩個標記$a,b$表示序列中的數爲$x$時實際表示的值是$ax+b$。對於一個單點賦值操做把值$x$變爲$(x-b)a^{-1}$放進數組裏面,對於全局賦值操做直接把數組清空。只清空在上一次清空到這一次清空之間被修改的數組上的位置,那麼清空的複雜度必定不會大於前面全部操做的操做次數,複雜度就是對的。spa

至於怎麼存這個數組能夠離散化也能夠像我同樣很呆地手寫哈希表遞歸

代碼字符串

染色(DP)

有一個顯然的暴力:設$f_{i,j,k}$表示填滿前$i$列、第$i$列兩個元素的顏色分別是$j,k$的方案數。複雜度三方一分都沒有……get

考慮在這個DP的狀態上壓掉一維。注意到若是咱們稱至少有一個位置有顏色的列是重要列,那麼若是咱們能夠預處理重要列與重要列之間的轉移,咱們就只須要記錄最後的重要列上$0$位置處填上的顏色便可,那麼DP的複雜度就變成了$O(n^2)$。it

感受很不錯,咱們考慮兩個重要列之間的可能狀態。設$x,y$是其中一個重要列的顏色,考慮另外一個重要列的顏色,有如下幾種狀況。在下面的敘述中用$?$表示不與$x,y$相同的顏色,一橫排的若干個矩陣表示這些矩陣的方案數是相同的。io

$\left(\begin{align*} x && ... && y \ y && ... && x \end{align*}\right)$搜索

$\left(\begin{align*} x && ... && x \ y && ... && y \end{align*}\right)$

$\left(\begin{align*} x && ... && ? \ y && ... && x \end{align*}\right)$ or $\left(\begin{align*} x && ... && y \ y && ... && ? \end{align*}\right)$

$\left(\begin{align*} x && ... && ? \ y && ... && y \end{align*}\right)$ or $\left(\begin{align*} x && ... && x \ y && ... && ? \end{align*}\right)$

$\left(\begin{align*} x && ... && ? \ y && ... && ? \end{align*}\right)$

設$g_{i,0/1/2/3/4}$表示這五種狀態中間全爲$0$的列數爲$i$時的填充方案數,轉移枚舉最後一個全爲$0$的列便可,係數有點複雜,可使用矩陣優化可是我這麼無腦的人確定是直接大力寫式子啊。

而後去掉頭尾的全$0$列(由於它們的方案數能夠直接貢獻到答案裏),咱們就能夠每一次枚舉兩列,用上面求出的$g$數組進行轉移了。複雜度$O(n^2)$能夠經過96pts。

因此最後的4pts固然是打表啦考慮優化DP。

當你寫出式子以後就能夠發現:其中的全部操做稍做變換能夠變爲「快速查詢」中的區間加、區間乘、單點修改、單點查詢、詢問全部的和的操做。寫一遍不須要離散化的快速查詢配上這個DP就能夠了。

96pts 100pts

世界地圖(最小生成樹、虛樹)

須要求一個前綴和一個後綴的最小生成樹,咱們能夠先預處理好前綴和後綴的生成樹,而後考慮鏈接前綴和後綴之間的邊的影響。

若是已經有邊鏈接了前綴和後綴,那麼若是再加入一條鏈接前綴和後綴的邊,那麼必定要刪掉兩個經度爲$1$的點在前綴最小生成樹上的路徑的最大邊權的邊,或者兩個經度爲$m$的點在後綴最小生成樹上的路徑的最大邊權的邊。那麼能夠發現前綴MST和後綴MST上有用的邊只是經度爲$1$和$m$的點的虛樹上的邊。

那麼咱們預處理先後綴MST的時候也使用一樣的方法,計算完MST以後把兩邊邊界上的點在MST上的虛樹記錄下來,注意到虛樹上一條邊的邊權能夠直接賦爲這兩個點對應MST路徑上的全部邊的最大邊權,那麼一個MST中有效的邊的數量就是$O(n)$級別的,每一次合併的複雜度就是$O(nlogn)$。

那麼這樣作就能夠獲得一個$O((m+q)nlogn)$的作法。

代碼

熱鬧的聚會與尷尬的聚會(構造)

題設至關於$(p+1)(q+1) \geq n$

考慮以下構造方式:每一次在圖中刪去度數最小的點和它所連的邊直至圖爲空,設每一次刪去的點的序列爲$p_1,p_2,...,p_k$,每個點被刪去時的度數爲$d_1,d_2,...,d_k$,那麼週日聚會就邀請$p_1,p_2,...,p_k$,週六聚會就邀請$d_i$取到最大值時對應的圖上的全部點。

證實:序列$p$的全部點顯然獨立,而$d_i$取到最大值時選擇的全部點的熱鬧度就是$\max d_i$。由於$\sum\limits_{i=1}^k (d_i + 1) = n$,$k(\max d_i + 1) \geq \sum\limits_{i=1}^k d_i +1 = n$,因此$(k+1) (\max d_i + 1) \geq n + 1$,因此這樣的選擇方案是合法的。

刪點使用set維護就能夠了。

代碼

移動金幣(階梯Nim、DP)

把第$i$個金幣和第$i+1$個金幣之間的空格個數看做第$m-i$節階梯的石子數量,那麼這個顯然是一個階梯Nim,有效的石子是奇數節的石子,而偶數節的式子對勝負沒有影響。

因此咱們只須要考慮奇數節的石子,而對於偶數節的石子直接組合數分配。計算先手獲勝的機率彷佛並很差算,可是比較好算的是先手必敗的方案數,由於這意味着奇數節階梯石子異或和爲$0$,也就是每一位剛好出現偶數次。發現$n$並非很大,咱們能夠直接按位揹包。複雜度是$O(mnlogn)$的,可是實際跑得很快。

代碼

連續子序列(記憶化搜索)

發現最近的省選很喜歡出思惟的搜索題(隔壁TJOID2T3就是,ZJOID1T1或許也能夠算)

以前有一個相似於$0110$縮成$0$、$1001$縮成$1$的方法,可是彷佛很難避免算重,而後發現有一種更優秀的作法……

考慮T.M.序列的一個性質,能夠參考OEIS A010060:令初始序列爲$0$,而後用$01$代替$0$,$10$代替$1$,作無限次就能夠獲得T.M.序列。

那麼若是一個序列是T.M.序列的子序列,也就必定可以經過$01$填充爲$0$、$10$填充爲$1$的方式還原爲$0$。

那麼咱們考慮dfs(s , k)表示當前前綴爲s、後面還須要填充k個字符的方案數,轉移能夠考慮枚舉填充的方式:有多是s的$x(2 \not\mid x)$與$x+1$字符組合,也有多是$x(2 \mid x)$與$x+1$字符組合,即在前面加上一個字符使得$s[1]$可以和這個字符組合,被一個單獨的字符填充。

不難發現當一個串的長度$>3$時這樣的劃分方式是惟一的,證實能夠不妨假設兩種填充的方式都成立,那麼若是在第一種填充方式下填充出了前綴$00$或者$11$,那麼在第二種填充方式下就會填充出前綴$000$或者$111$,這是不合法的;而若是填充出了$01$或者$10$,那麼在第二種填充方式下根本不可能存在合法的字符串知足條件。

而當串長度$\leq 3$時,好比說串$010$,它就能夠被填充爲$01|01$或者$10|10$,這兩種方案都合法,可是這個字符串只能被計數一次,因此這些地方須要特判。

注意到當$|s|=1$時方案數只和$k$的大小有關,在這種狀況下咱們能夠進入另外一層遞歸。在這層遞歸中使用記憶化,那麼總的狀態數就是$O(logk)$級別的,而solve函數的遞歸總數是$O(|s|)$級別的,因此複雜度很小能夠經過本題。

代碼

相關文章
相關標籤/搜索