做題記錄

開學之前博客一直處於咕咕咕狀態,原因有兩個,第一我懶,第二我沒圖

Owen 頹廢了一個八月,天天看番,開學前還打了幾部 gal...爲了防止自己頹廢,開了一個博客。


09.07

記得構造 (x,y) 選哪個的時候不能 swap! 九校 D1T3 就這麼掛了。。。


09.06

codeforces VP:

983,1208,1205,925,1137,1214.1178.

Codeforces Round #545 (Div. 1) (1137)

A. Skyscrapers

離散化一下,取個 max 即可。

B. Camp Schedule

猜結論,取最長 border. 這個東西可以 kmp, 然後就直接構造。

C. Museums Tour

暴力拆點,(x,i) 向 (y,i+1) 連邊。\(5\times 10^6\) 跑 tarjan 有點卡常,而且空間也有點卡。

D. Cooperative Game

一道不錯的老題,floyd 找環法。一個點速度爲 1,一個點速度爲 2,這時正好速度爲 1 的點在環上的距離 \(x\equiv -t(\text{mod}\ c)\),然後直接走 t 步就行了。步數大概是 3t+2c。

E. Train Car Selection

一道不錯的思維題。觀察性質,\(b,s>0\),那麼每次放多少個,開頭那個始終是最小的,並且若在開頭放 0,那麼 0 後面的數一定沒有貢獻,全部刪掉。若有 3 操作的話,我們維護兩個標記,全局加 k,b。我們對剩下的點維護一個下凸殼,全局加的時候就暴力把結尾不符合下凸殼的數刪掉。注意,因爲有全局加標記,所以剛開始放結尾的數一定是 \((n,-kn-b)\),n 是未加數時的序列長度。時間 \(O(m)\)

F. Matches Are Not a Child's Play

一道不錯的數據結構題。

我們先考慮整棵樹的最大值和次大值,每次刪除的時候肯定是刪成只有次大值到最大值的路徑,然後從次大值刪到最大值。那麼我們可以知道肯定是一條條鏈刪過來,這樣的話我們用最大值爲根,LCT 上每個 splay 維護子樹最大值到根的路徑。那麼現在我們只需要單點查這個點屬於哪個最大值,那麼答案肯定是最大值<當前最大值的鏈長+這個點到次大值的距離。

這個求前綴和是帶修的,所以用樹狀數組維護。加上先前的 LCT,時間 \(O(n\log^2 n)\),常數很小。


「2017 山東一輪集訓 Day7」逆序對

題意簡述:求長度爲 \(n\) 的逆序對數恰好爲 \(k\) 的排列個數,答案對 \(10^9+7\) 取模。\(n\leq k\leq 10^5\)

首先,第 \(i\) 個數可能會和前面的數產生 \(0,1,...,i-1\) 個逆序對,所以答案等價於求 \(0\leq a_i\leq i-1,a_1+a_2+...,a_n=k\) 的方案數。

解法一:(口胡)

類似付公主的揹包,考慮生成函數 \(F(x)=1\times (1+x)\times ...\times (1+x+x^2+...+x^{n-1})\)

然後我們找規律找出 \(\text{Ln}\ (1+x+x^2+...+x^n)\),調和級數算一算,多項式 \(\text{Exp}\) 算一算。不過模數不是 \(998244353\),要用 \(MTT\)

時間複雜度 \(O(n\log n)\)

解法二:

我們曾解決過一個 \(naive\) 的問題,求 \(a_1+a_2+...a_n=k\) 的方案數,但其中有 \(m\) 個數有限制,其中 \(a_{p_i}<b_i\)\(m\leq 20\)

我們知道上界不好處理,考慮容斥,枚舉哪幾個數突破限制,強制令這些數 \(a_{p_i}\geq b_i\),然後就可以把 \(k-b_i\),轉換成 \(simple\) 的問題——不定方程的非負整數解個數。

\(a_1+a_2+...a_n=k\),那麼不定方程非負整數解的個數爲 \(\Large{n+k-1\choose k-1}\)

現在我們也類似剛剛的方法,但這個上界比較特殊,我們可以 \(dp\)\(f[j][i]\) 表示選了 \(j\) 個數超過限制,\(\sum b=i\) 的方案數。

我們發現 \(dp\) 可以轉換成有一個容量爲 \(k\) 的揹包,物品體積爲 \(1,2,...,n\)每個物品只能放一次,求方案數。

如果我們直接揹包的話是 \(O(n^2k)\) 的,所以考慮優化,至少我們不能枚舉物品體積。

因爲這裏物品的體積是 \(1,2,...,n\),所以超出限制的數的個數不會超過 \(\sqrt{2k}\) 個。我們再轉換問題,求有多少個上升序列長度爲 \(j\),和爲 \(i\) 時,其中的數 \(\in [1,n]\)

因爲是上升序列,我們逆向差分一下,令 \(b_i=a_i-a_{i+1}\),那麼序列的和就變成了 \(\sum_{k=1}^{j}b_k\times k\),我們也只用保證 \(b_k>0\)

這樣就好 \(dp\) 了。

對於一個長度爲 \(j\),和爲 \(i\) 的差分後的序列,我們可以把最後一個數 \(+1\),也可以在最後添加一個 \(1\)\(f[j][i]=f[j][i-j]+f[j-1][i-j](i\geq j)\)

但是我們可能會出現 \(a_1>n\) 的情況,這時我們令 \(a_1=n+1\)\(f[j][i]-=f[j-1][i-n-1](i>n)\)

爲什麼令 \(a_1=n+1\) 是對的呢?

因爲每次 \(a_1\) 最多 \(+1\),每當 \(a_1=n+1\) 時,就會把不合法的減掉。如果從狀態 \(n+i\) 轉移到 \(n+i+1\),那麼前面 \(j-1\) 項和爲 \(0,1,..,i-1\) 時的情況都被減過了,只用再減去和爲 \(i\) 的情況就行了。

這樣愉快的 \(dp\) 部分就結束了。

現在只要枚舉超過的和 \(i\),把 \(dp\) 完的值乘上容斥係數後加起來再乘上 \(\Large{k-i+n-1\choose n-1}\)就行了。

時間複雜度 \(O(k\sqrt{k})\)


最近啃了一篇 rxd 的論文,關於樹上連通塊問題的,總結一下。

  • 若連通塊包含根,可以按照 dfs 序轉移,用揹包確定切掉哪些子樹。

  • 點數-邊數=1,可以配合上一條使用,就是算出強制包含一個點-強制包含一條邊的方案數,具體見完美的集合,因爲有個組合數取模我沒做。

  • 用線段樹合併維護整體 dp,PKUSC2019D2T1 就是整體 dp 的板子題,在線段樹上維護加法和乘法標記。有一些 dp 是在葉子結點只有有限個狀態,可以不用線段樹合併,用平衡樹合併,比如 ZJOI2019 Minimax 搜索和 PKUWC2018 Minimax。

  • 若是連通塊最優化或計數問題,可以在深度最淺處統計答案。如 Qtree6,7。

  • 動態 dp,一般寫樹剖就夠了,除非出題人惡意卡。對於一些乘法形式的 dp,我們選擇記錄答案和 0 的個數,額外開個結構體使 0 值可除。

  • 基於 LCT 的數據結構 Top Tree (沒學,咕咕咕)


腦子不夠用了,一些 sb 狀壓 dp 都想不出來,總結一下。

  • 最小/最大表示法,以最小/最大值表示一個集合,若有多個最小值用編號最小的那個。

  • 一個 dp 狀態難轉移,就開兩個,如限制每個點子樹大小的有根樹計數,可以用樹/森林的方案數來表示狀態。

  • 二進制不好表示狀態,可以用三進制,如給你一個最長上升子序列方案數。

  • 枚舉子集 \(O(3^n)\)

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