雜題選做Ⅰ


本博客將會收錄一些貪心/構造的我認為較有價值的題目,這樣可以有效的避免日后碰到 P7115 或者 P7915 這樣的題就束手無策進而墊底的情況/dk

某些題目雖然跟貪心關系不大,但是在 CF 上有個 greedy 的 tag,這種題目大概率也會被我收錄進來(比方說這篇博客里大概率會收錄不少 DP 題,因為 CF 上不少 DP 題都莫名其妙地打上了一個 greedy 的 tag

upd on 2021.11.30:由於更到后面發現后面的題目和貪心、DP 之類的關系不算太大了,倒是混入了不少計數題,故改名“雜題選做”,但是為了避免連接出鍋還是保留原來的 url。

1. CF1592F1 Alice and Recoloring 1

首先很明顯我們不會選擇翻轉包含 \((1,m),(n,1)\) 的矩形,因為它們完全可以等效於翻轉兩次包含 \((1,1)\) 的矩形,而前者代價不小於 \(2\),后者代價為 \(2\),因此我們只用考慮包含 \((n,m)\) 的矩形即可。

我們考慮記 \(a_{x,y}\) 表示 \((x,y)\) 格子顏色是否為黑色,再記 \(b_{x,y}=a_{x,y}\oplus a_{x,y+1}\oplus a_{x+1,y}\oplus a_{x+1,y+1}\),那么可以發現 \(1\) 操作等價於單點翻轉 \((x,y)\)\(b\) 值,而 \(4\) 操作等價於翻轉 \((x-1,y-1),(x-1,m),(n,y-1),(n,m)\) 四個點的 \(b\) 值,注意到一個性質就是我們 \(4\) 操作使用的次數肯定不會超過 \(1\),因為兩次操作 \(4\) 可以用六次操作 \(1\) 代替,而二者代價都是 \(6\),因此我們完全可以將兩次 \(4\) 操作變為 \(6\)\(1\) 操作且答案不會變得更劣。

這樣問題就簡單了,我們統計一下有多少個 \(b_{x,y}=1\),再統計一下是否存在一組 \((x,y)\),滿足 \(b_{x-1,y-1},b_{x-1,m},b_{n,y-1},b_{n,m}\) 均為 \(1\),如果存在則可以將這四次 \(1\) 操作變為一次 \(4\) 操作,答案減少 \(1\)

時間復雜度 \(\mathcal O(nm)\)

2. CF1592F1 Alice and Recoloring 2

和上一題一樣,我們同樣不會翻轉包含 \((1,m),(n,1)\) 的矩形,結論同上。

與上一題不同的是,由於此題翻轉 \((n,m)\) 的代價為 \(2\)​,因此“翻轉包含 \((n,m)\) 的矩形的次數不超過 \(1\)“這一結論就不再成立了,我們不妨來挖掘一下其他性質。我們記集合 \(S\) 表示 \(4\) 操作作用過的點,那么可以發現以下性質:

Observation 1. \(\forall (x,y),(x’,y’)\in S\),都有 \(x\ne x’,y\ne y’\)

因為如果我們翻轉兩個在同一行的元素,我們完全可以用 \(4\)\(1\) 操作代替兩次 \(2\) 操作。而二者擁有相同的花費。

Observation 2. \(\forall (x,y)\in S\),都有 \(b_{x-1,y-1}=b_{x-1,m}=b_{n,y-1}=1\)

否則翻轉完這個含 \((x,y)\) 的矩形后,肯定會有至少一個 \(0\) 變成了 \(1\),此時我們肯定要再花至少 \(1\) 的代價把這個 \(1\) 變回 \(0\),而這樣一來就已經有 \(3\) 的代價了,肯定不比直接翻 \(3\) 個點更優。

這樣一來模型就很明顯了,我們希望盡可能多地使用 \(4\) 操作,而使用 \(4\) 操作需要滿足 \(b_{x-1,y-1}=b_{x-1,m}=b_{n,y-1}=1\)\(x-1,y-1\) 互不重復,這樣能比不用 \(4\) 操作節省 \(1\) 的代價,這不禁令我們往二分圖匹配的方向去思考。具體來說我們建立兩排點,如果 \((x,y)\) 滿足 \(b_{x-1,y-1}=b_{x-1,m}=b_{n,y-1}=1\),那么我們就從左部的 \(x\) 點向右部的 \(y\) 點連一條邊,然后跑二分圖最大匹配即可知道我們最多可以使用多少次 \(4\) 操作,這樣通過網格上 \(1\) 的個數,減去二分圖最大匹配的大小即可得到答案。注意到每次使用 \(4\) 操作都會改變一次 \(b_{n,m}\),因此如果二分圖最大匹配是奇數,我們在統計網格上 \(1\) 的個數時,要反轉 \(1\) 的狀態。

3. CF1521D Nastia Plays with a Tree

徹底廢柴了/dk,連 2500 的貪心題都做不出來了

首先我們想到一個非常假的貪心:我們從上至下對樹進行一遍 DFS,然后每次嘗試將每個點的子樹變成一條鏈,如果發現兒子個數 \(\ge 2\) 就將那些分叉摘下來貼到一個兒子處。

該做法一臉過不去的樣子,離譜到連樣例都過不去,其原因在於它忽略了一種情況:那就是如果一個點的子樹有兩個分叉,並且兩個分叉都是一條垂下去的鏈,那么如果拋開這個點與其父親的邊,那么這個點的子樹也是一條鏈,因此合並時需要分情況討論。我們將“去掉一個點與其父親的連邊后,子樹是一條鏈”的子樹,分為“一條垂下去鏈”和“由兩條垂下去的鏈組合而成的鏈”兩種情況討論:

  • 如果這個點的子樹中,有至少兩條“一條垂下去鏈”,那么我們會選擇保留這兩條垂下去的鏈,合並成一條“由兩條垂下去的鏈組合而成的鏈”,然后其他鏈都接到這條鏈上。
  • 如果這個點的子樹中,恰有一條“一條垂下去鏈”,那么我們直接將其他鏈都接到這條鏈上形成一條更大的“一條垂下去鏈”即可。
  • 如果這個點的子樹中,沒有“一條垂下去鏈”,那么我們隨便選擇一條“由兩條垂下去的鏈組合而成的鏈”,然后將其余鏈都接到這條鏈上即可。

時間復雜度 \(\mathcal O(n)\)

4. CF1455F String and Operations

考慮 DP。注意到進行完前 \(i\) 次操作之后,\(s_{i+1}\) 要么在 \(i\),要么在 \(i+1\),取決於上一次 \(s_i\) 是否在 \(i\) 位置且上一次執行的是否是 R 操作。因此設 \(dp_{i,0/1}\) 表示進行完前 \(i\) 次操作后,\(s_{i+1}\) 否/是被移到了 \(i\) 位置后最小的字典序,轉移就分 OUDLR 五種情況轉移即可,時間復雜度 \(\Theta(n^2)\)

針對上述平方的 dp 我們其實還有進一步優化的空間。注意到每次操作我們只會影響 \([i-2,i+1]\) 這段區間內位置上的值,因此我們字符串只用存 \(4\) 位,每次 DP 過程中確定出 \(s_{i-3}\) 的最小值,然后從 \(s_{i-3}\) 達到最小值的位置轉移即可。這樣復雜度可優化到線性。

提交記錄

5. CF1474E What Is It?

一開始結論猜錯了,以為是 \(\sum\limits_{i=1}^{n-1}i^2\),后來對着錯誤的數據手玩之后才得到正確的結論/cg

結論:最大權值為 \((n-1)^2+(n-2)^2+(n-2)^2+(n-3)^2+(n-3)^2+(n-4)^2+(n-4)^2+\cdots\),如此加 \(n-1\) 個數得到的和。

構造:構造一個大小為 \(n\) 的置換環,上面的元素分別是 \(1\to n-1\to n-2\to n-3\to\cdots\to\lfloor\dfrac{n}{2}\rfloor+1\to n\to 2\to 3\to\cdots\lfloor\dfrac{n}{2}\rfloor\to 1\),然后操作 \(\lfloor\dfrac{n-1}{2}\rfloor\)\(1\)(即交換 \(1\)\(p_1\)),再操作 \(n-1-\lfloor\dfrac{n-1}{2}\rfloor\)\(n\) 即可。手玩一下即可發現這樣構造可以達到上面的上界。

證明:下面來證明下 \((n-1)^2+(n-2)^2+(n-2)^2+(n-3)^2+(n-3)^2+(n-4)^2+(n-4)^2+\cdots\)​ 是最大代價的上界。首先 \((n-1)^2\)​ 最多被貢獻一次,證明顯然,對於 \((n-2)^2\)​,顯然只可能 \((1,n-1),(2,n)\)​ 操作時會產生,因此最多產生 \(2\)​ 次貢獻,而對於 \(i\le n-3\)​,我們考慮歸納證明。顯然 \(i^2\)​ 的貢獻只可能在 \(1,2,3,\cdots,n-i,i+1,i+2,\cdots,n\)​ 這 \(2(n-i)\)​ 個數之間操作得到,而要想前面達到 \((n-1)^2+2(n-2)^2+\cdots+2(n-i+1)^2\)​​ 的上界,前面必須進行 \(2(n-i)-3\) 次操作,而合並 \(2(n-i)\) 個數至多可以進行 \(2(n-i)-1\),也就是說如果我們希望前面 \(2(n-i)-3\) 次操作的總收益盡可能大,\(i^2\) 只能貢獻兩次,如此歸納下去即可知道結論成立。

時間復雜度 \(\mathcal O(n)\)

6. CF1543E The Final Pursuit

一開始又猜錯結論了,以為 \(n\ge 3\) 第二問答案肯定是 \(-1\),又是根據錯誤的數據猜結論的一天(

首先第一問很容易,由於數據保證合法,因此可以隨便欽定一個點為 \(0\),並以任意順序欽定它們為 \(2^0,2^1,2^2,\cdots,2^{n-1}\)。然后 BFS 一遍即可,每次 BFS 時取出一個點 \(x\) 並將其所有鄰居的編號設為該點編號與該鄰居編號的 or。

難點在於第二問,手動構造 \(n=4\) 時我們有這樣一個感覺,就是 \(n\) 如果可以表示成 \(2^k\) 的形式,那么第二問答案就不是 \(-1\)。否則第二問答案就是 \(-1\)。碰到這樣形式的題我們可以很自然地想到歸納構造,具體來說 \(n=1\) 的構造是很 trivial 的,而假設 \(res_k\) 為當 \(n=2^m\) 時,點 \(k\) 的顏色,那么考慮根據 \(res_k\) 構造出 \(res’_k\) 表示當 \(n=2^{m+1}\) 時,點 \(k\) 的顏色。稍加思考可以得到:

\[res'_k=2^{m}·(\text{popcount}(\lfloor\frac{k}{2^m}\rfloor)\bmod 2)+(res_{\lfloor\frac{k}{2^m}\rfloor}+res_{k\bmod 2^m})\bmod 2^{m} \]

為什么這樣歸納構造出來的顏色序列符合要求?首先對於我們稱所有 \(\lfloor\dfrac{k}{2^m}\rfloor\) 相同的 \(k\) 為“同一塊”,那么每個點的所有鄰居中,恰好有 \(2^m\) 個與其在同一塊,另外 \(2^m\) 個與其不在同一塊中,顯然與其在同一塊的點,它們的 \(2^{m}·(\text{popcount}(\lfloor\frac{k}{2^m}\rfloor)\bmod 2)\)\(res_{\lfloor\frac{k}{2^m}\rfloor}\) 都是相同的,根據 \(n=2^m\) 的構造可知所有鄰居的 \(res_{k\bmod 2^m}\) 都是不同的,因此與其在同一塊中的鄰居的顏色不會重復,而對於不在同一塊之間的鄰居,由於它的鄰居與其異或起來一定是 \(2\) 的冪,且由於這些鄰居與其不在同一塊中,因此對於所有符合該要求的鄰居 \(k’\),都有 \(\text{popcount}(\lfloor\frac{k’}{2^m}\rfloor)\bmod 2\ne \text{popcount}(\lfloor\frac{k}{2^m}\rfloor)\),且 \(k’\equiv k\pmod{2^m}\),因此所有這樣的鄰居的 \(2^{m}·(\text{popcount}(\lfloor\frac{k}{2^m}\rfloor)\bmod 2)\)\(res_{k\bmod 2^m}\) 都是相同的,唯一不同的肯定是 \(res_{\lfloor\frac{k}{2^m}\rfloor}\),而如果我們把每一塊縮成一個點,那得到的肯定是一個 \(n=2^m\) 的圖,因此這些鄰居的 \(res_{\lfloor\frac{k}{2^m}\rfloor}\) 也互不相同。又因為對於與 \(k\) 在同一塊與與 \(k\) 不在同一塊的鄰居,它們之間的 \(\lfloor\dfrac{k}{2^m}\rfloor\) 的奇偶性必定完全不同,因此它們必然一類全部 \(<2^m\),一類全部 \(\ge 2^m\),不存在重復的情況。

7. CF1375E Inversion SwapSort

一道挺常規的題。

考慮歸納構造,每次將最大的元素還原到最右邊的位置處,而我們又不能改變剩余元素的相對位置關系,因此考慮將所有大於原來最后一個元素的數拎出來並按照它們的大小排成一列,假設為 \(a_{i_1},a_{i_2},\cdots,a_{i_k}\),那么我們的目標是 \(a_n\) 移到 \(a_{i_1}\) 的位置,\(a_{i_1}\) 移到 \(a_{i_2}\) 的位置,……,\(a_{i_{k-1}}\) 移到 \(a_{i_k}\) 的位置,\(a_{i_k}\) 移到 \(a_n\) 的位置,這個你就依次交換 \(n\)\(i_1\)\(n\)\(i_2\)\(n\)\(i_3\),……,\(n\)\(i_k\) 位置上的值即可,這樣既消滅了所有與 \(n\) 有關的逆序對,又實現了歸納。

8. CF1411F The Thorny Path

一道感覺難度中上的分類討論題。

首先特判掉 \(n=1\) 的情況,直接輸出 1 0 即可,沒啥好說的。

根據這篇博客證明的定理,根據 \(n\)\(3\)​ 得到的余數,最后我們拆分成的置換環大小可能的情況如下:

  • 如果 \(n\equiv 0\pmod{3}\),那么最后肯定剩下 \(\dfrac{n}{3}\) 個大小為 \(3\) 的置換環。
  • 如果 \(n\equiv 1\pmod{3}\),那么最后肯定剩下 \(\dfrac{n-4}{3}\) 個大小為 \(3\) 的置換環和兩個大小為 \(2\) 的置換環,或者 \(\dfrac{n-4}{3}\) 個大小為 \(3\) 的置換環和一個大小為 \(4\) 的置換環。
  • 如果 \(n\equiv 2\pmod{3}\),那么最后肯定剩下 \(\dfrac{n-2}{3}\) 個大小為 \(3\) 的置換環和一個大小為 \(2\) 的置換環。

考慮根據 \(n\)\(3\) 得到的余數進行分類討論:

  • 如果 \(n\bmod 3=0\)​ 那好辦,對於每個置換環我們肯定會先貪心的多拆些 \(3\)​ 出來,然后剩余的大小為 \(1,2\)​ 的置換環肯定是先 \(1\)​ 和 \(2\)​ 互相匹配,剩余落單的 \(1\)​ 或落單的 \(2\)​ 匹配,如果落單的是 \(1\)​,那么設 \(1\)​ 的個數為 \(c\)​,那么處理剩余 \(1\)​ 的最小交換次數為 \(\dfrac{2}{3}c\)​,如果落單的是 \(2\)​,那么設 \(2\)​ 的個數為 \(c\)​,那么處理剩余 \(2\)​ 的最小交換次數為 \(c\)​​。

  • 如果 \(n\bmod 3=2\)​ 也比較容易,我們枚舉最后一個 \(2\)​ 從哪里來,我們設所有置換環大小分別為 \(s_1,s_2,\cdots,s_k\)​,那么如果 \(\exists j,s.t.s_j\equiv 2\pmod{3}\)​,那么我們直接從這個置換環中拆出一個大小為 \(2\) 的置換環即可,否則我們就從兩個大小模 \(3\)\(1\) 的置換環中各拆出一個 \(1\) 出來。然后對剩余部分跑 \(n\bmod 3=0\) 的情況即可。

  • 比較棘手的是 \(n\bmod 3=1\) 的情況,按照 \(n\bmod 3=2\) 的套路,我們枚舉最后的零頭(也就是一個大小為 \(4\) 的置換環)的出處,有以下五種可能:

    • 從一個大小 \(\ge 4\) 且大小模 \(3\)\(1\) 的置換環中切出來。
    • 從兩個大小模 \(3\)\(2\) 的置換環中切出來。
    • 從一個大小模 \(3\)\(2\),兩個大小等於 \(1\) 的置換環中切出來大小為 \(2\) 的置換環,再合並兩個大小為 \(1\) 的置換環為一個大小為 \(2\) 的置換環。
    • 從一個大小為 \(3\) 的倍數的置換環中切出大小為 \(3\) 的置換環,再與一個大小為 \(1\) 的置換環合並成一個大小為 \(4\) 的置換環。
    • 由四個大小為 \(1\) 的置換環合並成兩個大小為 \(2\) 的置換環。

    仿照 \(n\bmod 3=2\) 的情況分類討論一下即可。我能說你會了 \(n\bmod 3=2\) 的情況不會討論 \(n\bmod 3=1\) 的情況就有點不太應該了嗎?

9. CF1381C Mastermind

首先,讀完題目我們可以很自然地產生這樣一個感覺:當 \(y\) 固定時,肯定是 \(x\) 越大,越有可能存在合法的解,因此我們肯定每次會想着貪心匹配出現次數最多的數。

我們不妨先考慮以下弱化版本:\(x=0,y=n\),那么顯然,如果出現次數最多的數的出現次數乘 \(2\) 大於 \(n\) 那答案就是 NO,否則我們將所有數按照其出現次數排成一排,譬如 \(1,2,3,1,2,1,2\) 排成一排就是 \(2,2,3,3,1,1,1\),然后我們先用出現次數最多的數去匹配前面的數,然后對於出現次數不是最多的數,我們就按照它們在上述序列中的順序依次往上填,譬如在上面的例子中,填出來的序列就是 \(1,1,1,2,2,3,3\),然后對應位置上的數依次匹配即可。

接下來考慮原問題,根據上面的推論,我們肯定希望出現次數最多的數的出現次數盡可能小,因此對於 \(x\)​ 個 \(a_i=b_i\)​ 的 \(i\)​,我們肯定會盡量選擇出現次數最多的值,這個可以 set 維護。比較困難的是 \(n-y\) 個不出現在原序列中的數即可,由於我們可以填的數的范圍為 \([1,n+1]\),因此必然存在一個數 \(\in[1,n+1]\) 且沒有在 \(a\) 中出現過,我們假設該數為 \(X\),記 \(mx\)\(a\) 序列中出現次數最多的數的出現次數,那么可以發現,如果 \((n-x-mx)+(n-y)<mx\),那答案就是 NO,否則,我們還是將剩余未被匹配的數按照上面的方式排成一列,即 \(1,2,3,1,2,1,2\) 排成 \(2,2,3,3,1,1,1\),然后我們從后往前填 \(X\),有多少個 \(n+1\) 就填多少個,然后對於出現次數最多的數,我們從前往后填,填到出現次數最多的數用完了或者下一個匹配的數就是出現次數最多的數為止,然后對於剩余的數,再按照順序填補剩余的空位,這樣說的可能不太清楚,舉個例子,如果序列為 \(1,2,2,3,3,3,3,3\),且 \(n-y=2\),那么我們先從后往前填兩個 \(X\),現在 \(b\) 序列變為 \(?,?,?,?,?,?,X,X\),然后我們從左往右填 \(3\),填上 \(3\)\(3\) 以后序列變為 \(3,3,3,?,?,X,X\),由於如果我們在第四個問號處填 \(3\) 就會出現自己與自己匹配的情況,因此我們只能填三個 \(3\),最后填補剩余空位,除去出現次數最多的數之后,剩余的序列是 \(1,2,2\),我們就按順序填即可,得到 \(3,3,3,1,2,X,X\),符合題意。

時間復雜度 \(n\log n\)

10. CF1214F Employment

\(a,b\) 從小到大排序,下面默認 \(a_i\le a_{i+1},b_i\le b_{i+1}\)

首先考慮一條鏈的情況如何處理,可以證明,對於一條鏈的情況,最小代價就是將 \(a\)​ 數組與 \(b\)​ 數組分別排序之后,對應項相減的絕對值之和,證明可用調整法,對於四個數 \(x,y,a,b\)​,如果 \(x\le y,a\le b\)​ 成立,那么一定有 \(|x-a|+|y-b|\le|x-b|+|y-a|\)​。

接下來考慮環上的情況,我們再次猜測一個性質,就是如果我們假設 \(a_1\)​​​ 對應的人選擇了 \(b_p\)​​​,那么 \(a_2\)​​​ 必然選擇 \(b_{p+1}\)​​​,\(a_3\)​​​ 選擇 \(b_{p+2}\)​​​,以此類推。因此考慮枚舉斷點 \(i\)​​​ 然后依次計算,暴力復雜度 \(\Theta(n^2)\)​​​ 顯然一臉過不去的樣子。不過發現在每對距離求解的式子中,\(a_i\)​​​ 的貢獻只有 \(a_i,-a_i,m-a_i\)​​​ 三種,\(b_i\)​​​ 也同理,因此考慮枚舉 \(a_i\)​​​,然后二分找到滿足 \(a_i\)​​​ 的貢獻為 \(a_i,-a_i,m-a_i\)​​​ 時,斷點 \(p\)​​​ 的區間,然后一遍差分即可求出當斷點 \(p\)\(1,2,3,\cdots,n\) 時,所有人移動的最短距離之和。

時間復雜度 \(n\log n\),細節略有點多(

11. CF1372E Omkar and Last Floor

首先看到類似於 \(f(x)=x^2\) 這樣的凸函數,我們可以很自然的往貪心的方向聯想,具體來說對於某一列,我們感性的理解一下,如果它已經填了比較多的 \(1\),那么我們會盡可能在這一列上多填 \(1\),而不是再在其它列上填 \(1\)

受到這個思想的啟發,我們可以想出如下的貪心:我們選擇一列,然后考察所有區間,如果該區間中當前沒有填 \(1\),並且我們選擇的這一列屬於這個區間,那么我們就在這個區間上填上 \(1\),否則我們不對該區間進行任何操作。然后遞歸地對剩余地矩陣進行操作即可。

考慮區間 dp 優化上述過程。我們設 \(dp_{l,r}\)​ 表示當前操作了 \([l,r]\)​ 中的列,恰好所有包含於 \([l,r]\)​ 中的區間中有位置被填上 \(1\)​ 的最大權值之和,那么顯然有轉移 \(dp_{l,r}=\max\limits_{k=l}^rdp_{l,k-1}+dp_{k+1,r}+s_{k,l,r}^2\)​,其中 \(s_{k,l,r}\)​ 表示有多少個區間 \([l’,r’]\subseteq[l,r]\)​,且 \(k\in[l’,r’]\)​。這個可以前綴和求出,時間復雜度 \(nm^2+m^3\)​。

12. CF1430F Realistic Gameplay

考慮我們應采用如何的策略。首先只要我們槍中還有彈,並且前面還有怪沒被殺死,那么我們肯定會一直開槍。如果我們當前這波怪沒有打死,並且槍中沒彈了,那我們肯定會換彈,唯一不確定的事情是打完當前這波怪之后我們換不換彈,如果我們換了彈,那么帶來的后果有兩個,一是原來的彈被浪費,二是由於 \(l_{i+1}\ge r_i\)​​,因此如果換彈的時刻剛好是 \(r_i\)​​,而 \(l_{i+1}=r_i\)​​,那就會導致下一波怪只能從 \(l_{i+1}+1\)​​ 時刻開始才能打。因此考慮 DP。\(dp_{i,j}\)​​ 表示打第 \(i\)​​ 波到第 \(n\)​​ 波的怪,第 \(i\)​​ 波怪從時刻 \(l_i+j\)​​ 才能開始打,目前彈夾是滿的,最少要花費多少彈才能打死所有怪,其中 \(j\in\{0,1\}\),枚舉下一次什么時候把當前的這波怪打完后換了彈夾即可實現 \(\Theta(n^2)\) 求解 DP 數組。

據說有線性做法?orzorz(

13. CF1493E Enormous XOR

詐騙題一道(

首先特判掉 \(r=0\) 的情況。

如果 \(l\) 的最高位為 \(0\),那么由於 \(r\) 的最高位為 \(1\),答案顯然是 \(111…11\),構造 \(l=2^{n-1}-1,r=2^{n-1}\) 即可。

如果 \(l\) 的最高位為 \(1\),先特判掉 \(l=r\) 的情況,此時答案顯然就是 \(l\)

不難注意到一個性質,就是對於偶數 \(x\)​,有 \(x\oplus(x+1)=1\)​,因此我們如果去掉 \([l,r]\)​ 中所有滿足 \(x\)​ 為偶數的相鄰對 \((x,x+1)\)​,那最后必定剩下 \(0\)​ 或 \(1\)​ 或 \(2\)​ 個數以及一車 \(1\)​。而顯然如果最后剩兩個數肯定是不優的,因為這樣最高位必定為 \(0\)​,\(0\)​ 個數的情況只可能是 \(0/1\)​ 也不太行,因此只可能是一個數的情況最優,而顯然我們會想讓剩下的那個數為 \(r\)​,然后剩下的一車 \(1\)​ 的奇偶性與 \(r\)​ 奇偶性不同,這樣異或起來可以達到理論上界 \(r\text{ or } 1\)​,但是這樣有可能是不可行的。具體來說,如果 \(r\) 本身就是奇數那取 \([r,r]\) 即可達到理論上界,如果 \(r\) 是偶數,且 \(l\le r-2\) 那取 \([r-2,r]\) 也可以達到理論上界,但如果 \(r\) 是偶數且 \(l=r-1\) 那最大值只有 \(r\),達不到 \(r+1\),特判一下即可。

14. CF1492E Almost Fault-Tolerant Database

首先顯然答案數組可以在第一行的基礎上修改兩個元素得到,因此考慮以第一行為基准,求一遍第一行與其余行有多少個不同的元素。

如果存在一行,滿足第一行與該行不同元素個數 \(\ge 5\),答案就是 NO。

如果與第一行不同元素最多的行與第一行的不同元素個數 \(\le 2\),直接輸出第一行即可。

如果與第一行不同元素最多的行與第一行的不同元素個數 \(=4\)​,那么可能成為答案的數組顯然只有 \(6\) 個,依次 check 一遍即可。

如果與第一行不同元素最多的行與第一行的不同元素個數 \(=3\),我們假設第 \(i\) 行與第 \(1\) 行有 \(x,y,z\) 三個元素不同,那么我們對於所有 \(3\times 2\) 種情況(\((x,y),(x,z),(y,x),(y,z),(z,x),(z,y)\)),依次檢驗一遍,具體檢驗方法是,以 \((x,y)\) 為例,先假設 \(ans_x=a_{1,x},ans_y=a_{i,y}\),然后掃一遍整個矩陣,如果不存在某一行與 \(ans\) 不同元素數量 \(\ge 3\) 就輸出 \(ans\),否則我們假設第 \(j\) 行與 \(ans\) 不同元素數量 \(\ge 3\),那么我們令 \(ans_z=a_{j,z}\),然后再跑一遍即可。

時間復雜度 \(\Theta(18nm)\)

15. CF1487F Ones

小清新數位 dp 題,怎么混進我的 blog 的(bushi

考慮從高位到低位確定每一位 \(d\),總共加/減了多少次 \(\dfrac{10^{d+1}-1}{9}\),也就是 \(d\)\(1\) 組成的數,注意到如果我們欽定到第 \(d\) 位,那么此時的 \(n\bmod 10^d\) 可以用兩個參數 \(c,p\) 來描述,即設 \(n’\) 表示此時的 \(n\),那么有 \(n\equiv (-1)^pn’+c·\dfrac{10^{d+1}-1}{9}\pmod{10^d}\)。這樣就可以 DP 了,設 \(dp_{d,c,p}\) 表示目前考慮到第 \(d\) 位,高於 \(10^d\) 的位都已被清零,目前 \(n\equiv (-1)^pn’+c·\dfrac{10^{d+1}-1}{9}\pmod{10^d}\),最少需要多少次操作才能將 \(n\) 變為 \(0\),轉移就枚舉如何將 \(10^d\) 位變成零即可,一種是直接減若干次 \(\dfrac{10^{d+1}-1}{9}\),還有一次是先用 \(\dfrac{10^{d+2}-1}{9}\) 減去 \(n\),再減去若干次 \(\dfrac{10^{d+1}-1}{9}\),兩種情況分別討論一下即可,比較煩的一點是要手寫高精。

時間復雜度 \(9\log_{10}(n)^3\),常數很小。

16. CF1422E Minlexes

首先吐槽一句,這題 pretest 真是……寫了一個完全錯誤的做法竟然能一連艹過前 45 個點……出題人怕不是用腳造數據,\(n=4\) 的情況我原來寫的做法都有鍋

考慮 DP。\(dp_i\) 表示 \([i…n]\) 后綴的答案,那么分兩種情況轉移:

  • \(s_i\ne s_{i+1}\),顯然 \(s_i\)​ 必須保留,故 \(dp_i=s_i+dp_{i+1}\)
  • \(s_i=s_{i+1}\)​,此時有兩種可能,要么刪掉 \(i,i+1\)​,\(dp_i=dp_{i+2}\)​,要么保留 \(s_i\)​​,\(dp_i=s_i+dp_{i+1}\),因此只要對上述兩個 \(dp\) 值取個 max 即可。

對於第一種情況,手寫一個結構體保存每個字符串前后 10 個字符即可 \(\mathcal O(1)\) 插入。比較麻煩的是第二種情況。直接比較是平方的,一臉過不去的樣子。不過注意到在頭部插入一個字符后字典序變小,等價於對於從左往右數第一對不同的字符 \(i,i+1\),滿足 \(s_i<s_{i+1}\),因此在結構體中額外記錄一個變量,表示第一對相鄰且不同的字符的大小關系即可。

時間復雜度 \(\mathcal O(n)\)

17. CF1420E Battle Lemmings

首先看到交換次數以及這題 \(n\le 80\) 的數據范圍,我們可以很自然地想到將交換次數放入 DP 狀態的套路,即設 \(dp_{x,y,k}\) 表示目前填了 \(x\)\(0\)\(y\)\(1\),逆序對個數為 \(k\),並且最后一位為 \(1\),最多能有多少對 \((i,j)\) 滿足 \(a_i=a_j\)\([i+1,j-1]\) 中所有數不全為零,轉移就枚舉下一段 \(0\) 的長度 \(len\),那么有 \(dp_{x+len,y+1,k’}\leftarrow dp_{x,y,k}+len·x\),其中 \(k’=k+\sum\limits_{i=1}^{len}\max(pre_{i+x,0}-y,0)+\max(pre_{y+1,1}-(x+len),0)\),其中 \(pre_{i,0}\) 表示原序列中第 \(i\)\(0\) 前面有多少個 \(1\)\(pre_{i,1}\) 表示原序列中第 \(i\)\(1\) 前面有多少個 \(0\)。時間復雜度 \(n^5\),但由於常數極小,可以通過。

實際上這題還有 \(n^4\) 的做法,然鵝大概由於那天肝了一道 287 行代碼 10000+ 個 B 的毒瘤題,這個做法就鴿掉了

18. CF1225F Tree Factory

一開始猜了個錯的結論(按子樹 size 貪心),然后 WA 6,不愧是我(

首先答案下界顯然是 \(n-\max\limits_{i=0}^{n-1}dep_i\)​,其中 \(dep_i\)​ 表示 \(i\)​ 到根節點路徑上的點數,因為每次操作最多使整棵樹深度最深的節點的深度減少 \(1\)。考慮構造使其達到這個下界。

我們對整棵樹進行一遍 DFS,當我們 DFS 到點 \(u\) 時,我們將每個節點所有兒子按照其 \(mxdep\) 從小到大排序,然后每次按 \(mxdep\) 從小到大的順序依次遍歷每個兒子,假設當前遍歷到節點 \(v\),那么我們就將當前鏈上端的 \(siz_v\) 個節點做成 \(v\) 子樹的形態,如果 \(v\) 不是最后一個兒子,那么我們就不斷執行操作上推這條鏈上第 \(siz_v+1\) 個節點下端的鏈直到這個點的父親為 \(u\) 為止,不難發現該做法的時間復雜度與長鏈剖分復雜度類似,具體來說,對於一條鏈,假設其鏈頂節點為 \(u\),其父親為 \(f\),那么當我們 DFS 到 \(f\) 時,會進行 \(mxdep_u\) 次上推操作,因此操作次數就是所有長鏈的長度之和,根據長鏈剖分那套理論可知所有長鏈的長度之和為 \(n\)。特別地,\(1\)​ 所在的長鏈是不會產生貢獻的,因此需減去 \(mxdep_1\),由此可知操作次數為 \(n-mxdep_1\)

19. CF650E Clockwork Bomb

首先如果一條邊在兩棵樹中都出現過,那么我們肯定不會選擇斷掉這條邊,因此我們考慮將這些邊的兩個端點 merge 起來。我們記這樣的邊的條數為 \(c\),那么答案的下界顯然為 \(n-1-c\),我們還是通過構造達到這個下界。

我們稱縮點過后的第一棵樹為 \(T_1\),縮點過后的第二棵樹為 \(T_2\),兩棵樹都以 \(1\) 為根節點。那么我們找出 \(T_1\) 的一個葉子節點 \(x\),找出它在第二棵樹上對應的節點 \(y\)。我們斷開 \(x\)​ 在第一棵樹上與其父親之間的邊,並連上 \(y\) 在第二棵樹上與其父親之間的邊——顯然,由於 \(x\) 是葉子節點,此時 \(y\) 與其在第二棵樹上的父親在第一棵樹中不在同一連通塊中,因此這樣一斷一連並不會出現環,這樣我們就通過一次操作使同時在兩棵樹中的邊數加一,此時我們就可以在兩棵樹中把新加的邊用並查集合並起來,如此歸納下去即可。

具體實現時可對第一棵樹進行一遍 DFS,遍歷一個點 \(x\) 的子節點 \(y\) 時,我們考察 \(x,y\) 是否在並查集同一連通塊中,如果在則忽略它不管,否則我們找到 \(y\) 所在並查集中第二棵樹上深度最小的節點 \(u\),然后合並 \(u\)\(u\) 在第二棵樹上的父親。

時間復雜度 \(n\alpha(n)\)

20. CF1469F Power Sockets

嗯沒錯就是我現場 AC 的那道 edu F,現在我們來用復雜度更優秀的做法來水這道題(

首先講講我賽時的做法,首先很明顯的一個事實是,我們加入一條鏈的時候,肯定會選擇將鏈的中點與當前樹中深度最淺的白點連接,那我們就用線段樹模擬這個過程唄,設 \(f_i\) 表示距離為 \(i\) 的白點個數,那么我們將鏈按長度從小到大排序,每次在線段樹上二分找到第一個 \(f_i\) 非零的位置,將其減去 \(1\),然后執行兩遍區間加。然后每次加入完一條鏈就再進行一遍線段樹二分找出第 \(k\) 個白點的位置更新答案即可。

這樣復雜度是 \(n\log n\) 的,常數較大。我們考慮復雜度更優秀(至少常數更小)的做法:不難發現,每次我們找到的 \(f_i\)​ 非零的位置是單調不降的,這讓我們很自然地聯想到雙指針,具體來說我們每次區間加時維護序列的差分數組,然后每次加入一條鏈時雙指針找到下一個非零的位置,同時再開一個指針維護第 \(k\) 近的白點位置,這樣除去排序可以做到線性,使用基數排序可使整個程序做到線性。

21. CF1394D Boboniu and Jianghu

首先吐槽一句,這題的數據有億點點水啊,一開始寫了個 \(\sum deg^2\)​ 的做法竟然 AC 了(

首先考慮如果這題 \(h_i\) 互不相同如何解決,我們設 \(dp_i\) 表示將 \(i\) 子樹中的邊以及 \(i\) 與其父親的邊划分成若干條鏈的最小權值之和,考慮如何轉移,我們枚舉 \(u\) 的所有兒子 \(v\),那么顯然我們可以將 \((u,v)\) 這條邊分為兩類:\(h_u>h_v\)\(h_u<h_v\)。我們首先將所有 \((u,v)\) 所在的鏈向上延伸一格,此時我們多余的貢獻就是 \(a_u\) 乘以點 \(u\) 兒子的個數,但是這樣不見得是最優策略,我們可以選擇將一個 \(h_u>h_v\) 的鏈與一個 \(h_u<h_v\) 的鏈合並成一條鏈,這樣我們可以少一個 \(a_u\) 的代價。如果我們記 \(h_u>h_v\) 的兒子數為 \(c_1\)\(h_u<h_v\) 的兒子數為 \(c_2\),那么我們最多可以合並 \(\min(c_1,c_2)\) 次,可以減少 \(\min(c_1,c_2)·a_u\) 的代價。此外,如果 \(u\) 不是根節點,我們還要選擇一條鏈向上延伸,這里有兩種選擇,要么直接 \(u\) 單獨成一條鏈,代價 \(a_u\),要么選擇一條鏈向上延伸,這條鏈不參與匹配,如果 \(h_{fa_u}>h_u\),那么剩余的鏈還能匹配 \(\min(c_1-1,c_2)\) 次,否則剩余的鏈還能匹配 \(\min(c_1,c_2-1)\) 次。

接下來考慮沒有 \(h_i\) 互不相同的條件怎么辦,顯然對於 \(h_u=h_v\)\((u,v)\),它既可以充當 \(h_u>h_v\) 的鏈,也可以充當 \(h_u<h_v\) 的鏈,我們就設 \(dp_{u,0/1}\) 表示匹配了 \(u\) 子樹內的邊,\(u\) 向上延伸的鏈為單調不增/單調不降的鏈的最小代價。考慮如何轉移,我們枚舉 \(u\) 的兒子 \(v\),然后先假設所有 \(v\) 都選擇 \(dp_{v,1}\),將所有兒子按 \(dp_{v,0}-dp_{v,1}\) 排序,然后按照套路還是枚舉選擇了多少個兒子 \(v\) 滿足 \((u,v)\) 屬於一個單調不增的鏈,然后 \(\mathcal O(1)\) 計算 DP 值即可。

時間復雜度 \(\Theta(n\log n)\)

22. CF524F And Yet Another Bracket Sequence

首先考慮一個非常重要的性質:一個字符串可以僅通過 cyclic shift 變成 RBS,當且僅當括號串中左右括號個數相等。必要性顯然,充分性證明大概就可將一個括號序列看成一個每段斜率都是 \(\pm 1\) 的折線,然后取折線最低處為起點即可使折線上處處高度高於起點。

有了這個性質之后,最少添加的括號的個數就很好確定了,設 \(c\) 為左括號個數減去右括號個數,那么最少需要添加 \(|c|\) 個括號。而關於字典序最小的序列,我們肯定會貪心地選擇在序列開頭添左括號 / 在序列末尾添右括號,這樣括號序列字典序最小,就等價於去掉新添加的括號后,得到的括號序列字典序最小,因此可以直接枚舉端點,ST 表判斷括號序列是否合法,后綴排序 / 哈希判斷字典序大小。時間復雜度 \(\Theta(n\log n)\)

23. CF1601D Difficult Mountain

首先看到類似這樣給定幾個二元組/三元組,要按順序選出一些元素滿足個什么條件,求選出元素個數的最大值的題目,我們一般考慮將這些二/三元組按個什么東西為關鍵字排個序,使得在最優策略中我們肯定在排好序的數組中中從前往后選,這樣我們就可以進行線性 DP 了。此題也不例外,經過一番觀察我們發現如果 \(p_i·a_i<p_j·a_j\)​,那么 \(i\)​ 一定比 \(j\)​ 先爬山,一個比較感性的理解方式是,如果 \(p_ia_i<p_ja_j\)​​,那么必然有 \(p_i<a_j\)​ 或 \(a_i<p_j\)​,對於前者,后一個人爬完了前一個人肯定不會爬,因此我們肯定貪心地把后一個人安排在后面,對於后者,前一個人是否成功登山對后一個人的情況不會產生影響,可以放心大膽地把它放在前面。

這樣就可以 DP 了。設 \(dp_i\) 表示當前山的高度為 \(i\) 最多有多少個人能成功登山,離散化+線段樹優化 DP 即可,具體來說如果 \(p_i<a_i\) 那我們求 \([0,p_i]\) 的區間最大值然后令 \(dp_{a_i}\) 對該最大值取 \(\max\),如果 \(p_i\ge a_i\) 則令 \([a_i+1,p_i-1]\) 區間加 \(1\),然后求一下 \([0,a_i]\) 的區間最大值並令 \(dp_{a_i}\) 對該最大值取 \(\max\),時間復雜度 \(\Theta(n\log n)\)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM