9 月 CSP 模擬賽瞎記


每道題口胡一句話。

9.1

今天怎么 6 題,說是手速場,我咋一道都不會啊。

T1

差分。

T2

首先一定可以得到每條邊只能被覆蓋 \(0\) 次或 \(1\) 次。然后做樹形 DP,記錄 \(f_0(u),f_1(u)\) 分別表示 \(u\) 子樹是否向上連邊的最小代價(次數和邊數)。用插頭的形式表示次數,即在一次操作的兩端的邊改變插頭狀態。轉移時合並各兒子,討論 \(0/1\) 狀態之間的轉化。

T3

不互質的數一定要在一塊,並查集一下,\(1\) 特殊處理,答案是 \(2\) 的冪。

T4

在 01-trie 上 dfs,記錄合法點集,轉移用 \(\texttt{std::bitset<>}\) 就過了。

T5

考慮 DP \(F_i(S)\) 表示到第 \(i\) 條邊 \(S\) 集合都存在的概率是否大於零。轉移:

\[f_i(S)\gets\begin{cases} \mathrm{none}&u\in S \land v\in S\\ f_{i-1}(S\cup\{u\})\lor f_{i-1}(S\cup\{v\})&u\in S \lor v\in S\\ f_{i-1}(S)&u,v\not\in S\\ \end{cases} \]

那么 \(u\) 最后存在概率大於零當且僅當 \(f_m(\{u\})=\mathrm{true}\)。狀態數很多,但是終止狀態固定,我們考慮倒推。

\(f_m(\{u\})=\mathrm{true}\),最后可以得到唯一的集合 \(G_u\) 表示得到 \(u\) 所必須刪去的集合。

那么兩個點 \(u,v\) 都存在的概率大於零當且僅當 \(G_u\cap G_v=\varnothing\),因為一個點不能夠被刪去超過 \(1\) 次。

\(\texttt{std::bitset<>}\) 實現,復雜度 \(\mathcal O(nm+n^3/\omega)\)

T6

一個點可以到達的點集奇偶性相同,先分類。然后 bfs,用 \(\texttt{std::set<>}\) 維護未訪問點集,訪問一次后刪去,可以保證復雜度。


9.3

暴力都能寫假。

T1

又是分塊。

T2

巧妙的 DP。按 \(y\) 從小到大 DP 是在沒法優化。考慮按 \(x\) 坐標排序,統計每個點作為路徑結尾最左 / 右端的貢獻,每次枚舉路徑最左端,然后從 \(y\) 坐標較小的點向較大的點轉移。

這樣其實 DP 是沒有后效性的,只是隱式的建了分層圖。

T3

每個前綴后繼狀態唯一,manacher 預處理然后倒序轉移一下可行性。

T4

首先有一段被操作的建築會被增加至相同高度的結論,考慮枚舉相鄰的不變點進行轉移,代價函數為 \(w(t)=\sum_{l<i<r}(t-h_i)^2+(h_l+h_r-2t)\times c\) 拆開后是關於 \(t\) 的二次函數,求對稱軸算極值可以 \(\mathcal O(1)\)

大部分轉移是無用的,只需要在高度最接近的點對轉移,用單調棧即可 \(\mathcal O(n)\)


9.4

今天表演了一波寫三題掛三題,狀態差到極點。

T1

每個人的最優策略都是盡量占領兩者之間的那條鏈。

\(\texttt{size[v] += size[u];}\)

T2

處理兩點之間夾着的點集,然后是裸的狀壓。

題意最后求什么要仔細看哦。

T3

球的狀態分為自己滾和被人帶,自己滾因為兩個方向無法之間轉換,考慮建三層分層圖。

最優方案下一個人最多經手一次球,否則可以調整為更優。因此可以 bfs 處理每個點最近的人的距離,也就是球從自己滾的狀態轉為被人帶的狀態的代價。

最短路就好了。

T4

分類討論,然后套上倍增。

\(E\)定值,以 \(E\) 為根會好做很多。


9.6

T1

可以發現最小的兩個數一定是 \(a_1+a_2,a_1+a_3\),考慮枚舉 \(a_2+a_3\) 是哪個數,就可以算出 \(a_1\),然后就可以順推其它數了。\(a_2+a_3\) 只用枚舉到前 \(n\) 個,就可以 \(\mathcal O(n^3)\)

T2

答案和逆序對奇偶性有關,只有奇數逆序對數的排列不合法。答案就是 (積和式 - 行列式) / 2,矩陣很特殊所以可以 \(\mathcal O(n^2)\) DP。

T3

篩出 \(\sqrt R\) 的素數,然后 \([L,R]\) 內枚舉素數倍數進行埃氏篩。


9.8

水題大賽,不說了。


9.10

T1

每次詢問滿足 \(l < L \le r\lor l\le R < r\) 的區間 \([l,r]\) 的數量。

可以發現是樹上兩條鏈的並,倍增找起點。

卡常,要用樹剖 LCA。

T2

\(1e18\) 內至多 \(15\) 個質因子,直接子集 DP。

單價函數 \(f(V)\)\(p\) 很小,考慮做同余最短路。

T3

折半。

T4

枚舉每個葯丸作為最后一個,那么剩下的一定是按 \(a_i-b_i\) 從大到小取。

難點在於判斷是否合法,先排序,對於 \(i\) 作為結尾, \(1\dots i-1\) 合法性可以直接預處理,而 \(i+1\dots n\) 的點是於前面一位的 \(c_i\) 做差然后前綴和,也就是不斷的往開頭插入數、動態維護所有點的前綴和。

用權值線段樹維護單點插入、整體加、查詢權值范圍內編號最小值,即可找到 \(i\) 之后第一次被淹的位置。

另外一個爛大街的貪心做法:二分答案天數 \(\mathrm{mid}\),然后每次 \(1\dots \mathrm{mid}\)\(b_i\) 最大的作結尾,和 \(\mathrm{mid}\dots n\)\(a_i\) 最大的作結尾,兩種方案取最值。對於合法性,可以發現每次 \(1\dots \mathrm{mid}\) 無法移動至結尾的點是一個前綴,遞推找到合法的范圍。

upd:這東西完全不需要二分。


9.12

T1

DP 類似中國象棋。觀察性質是每放玩一個或一對點,其中每個點對應的行列都不能再放。那么狀態記錄當前空的列,然后按行轉移。

T2

Dilworth 引理,離線下來然后是二維偏序。

T3

考慮對於任意一個集合,去掉權值最大的元素后,可以唯一的變成一個優於它的集合。這是一個樹形的結構,考慮類似超級鋼琴的套路,用堆來找出第 \(k\) 大權值。

不過復雜度仍然不對,因為樹上每個點的兒子數是 \(\mathcal O(n)\) 的,但是可以發現這些兒子之間的單調性,考慮轉成二叉樹。也就是將 \(a\) 序列排序后,每次對於一個集合 \(S\) 及其結尾元素編號 \(i\),其拓展出的兒子為 \(S\cup\{a_{i+1}\}\)\((S\setminus \{a_i\})\cup\{a_{i+1}\}\)

構造方案:既然權值小於等於 \(\mathrm{ans}\) 的方案不超過 \(k\) 個,那么直接搜索。從小到大每次加入一個元素使得權值和不超過 \(\mathrm{ans}\),用線段樹或者主席樹來找到編號范圍內小於等於某個權值的最小編號,因為遍歷到的每個方案權值和都 \(\le \mathrm{ans}\),所以復雜度 \(\mathcal O(k\log n)\)

T4

\(\sum |t_{i+1}-t_i|\) 這樣的式子,畫在數軸上就是點移動的距離和,加上時間一維變成二維坐標系,發現是裸的線頭 DP。

線頭 DP 注意兩端邊界是否到達要記錄進狀態里。權值和 \(>L\) 的狀態舍棄,復雜度 \(\mathcal O(n^2L)\)


9.13

T1

如果條件是 \(L\le\mathrm{mid}\le R\) 的話,對應的答案就是區間內 \(1\) 的個數為奇數的區間數。然后再減去只有一個 \(1\) 並且位置在 \(L\)\(R\) 上的區間數。

T2

樹上每個點對應的兩個兒子是一定的,那么確定了根也就確定了所有葉子各種類的數量。那么可以判斷給出的三個數是否合法。

然后是構造字典序最小的解。可以發現每個高度只有 \(3\) 棵本質不同的樹,可以直接遞推,暴力比較字典序,讓字典序較小的在前,復雜度 \(\mathcal O(2^n)\)

T3

如果 \(n=m\),可以有 naive 的 \(\mathcal O(n^2)\) DP。

因為觀察 DP 過程,如果令較大數相乘一定更優,所以將序列排序,最后選的一定是一個前綴和一個后綴,做上面的 DP 再枚舉長度進行拼接。

T4

暴力能過。/jy


9.15

打了兩個小時瞌睡。

T1

相鄰的同色點配對后刪掉,對其他點是沒有影響的。不斷重復這個過程,最后剩下 \(\texttt{010101}\dots\),此時只能夠異色配對。

用棧來實現。

T2

\(m\) 非常小,把每個數的所有約數都暴力找出來即可。

T3

體積很大但是價值很小,把價值當作體積做背包。

修改很少查詢很多,那么每次做完背包后,二分找到最大的價值滿足其最小體積不超過 \(M\),做一個后綴 \(\min\) 即滿足單調性。

T4

二分,合法條件為存在區間滿足 \(\gcd=\min\)\(\mathcal O(n\log n)\)

處理每個點作為 \(\gcd\) 所能擴展的最大區間。若 \(a_i\mid a_{i+1}\),那么 \(a_{i+1}\) 邊界包含於 \(a_i\) 的最大邊界,\(a_{i+1}\) 一定更劣。據此可以做到 \(\mathcal O(n)\)

T5

考慮每個數 \(a_i\) 在每個位置,對 \(j\) 為開頭時的貢獻。

可以發現是兩段等差數列,然后向左 \(i-1\) 位的循環偏移,可以二階差分。

T6

行列之間的連通性是不影響的。我們直接去做 Kruskal 最小生成樹,每條橫向的邊代表的是 \(n\) 條邊,連接兩列,因為有若干行在這兩列上已經連通,我們只用連剩余行連通塊數條邊;豎向的邊類似。

那么只需要把 \(n\) 行、\(m\) 列都看作點,對 \(P+Q\) 條邊做 Kruskal,計算貢獻時記得加權。


9.17

T1

兩個方向 DP 然后拼一下。

T2

轉化為求異色邊。對於父親暴力修改,兒子用 \(\texttt{std::map<>}\) 維護。

T3

\(k\) 分塊,每次就只需要 \(\mathcal O(W)\) 合並兩個背包。

需要注意開空間,用內存池和指針為好。

T4

每個點記錄前 \(k\) 小路徑,轉移時只需要對兩個有序序列歸並,\(\mathcal O(nk)\)


9.18

T1

每次移動一格起點,變化的位置只有 \(3K\) 個,只考慮這些位置產生的增量。

T2

貪心。最后的局面一定是一個環,首先每個點至多一個入度,所以保留最大的入邊。

此時會形成若干環和若干鏈,我們要破環成鏈,若干鏈一定是能拼成環的。此時環上不能直接斷掉邊權最小的邊,因為斷開環后端口點可以和它的其它入邊連接成新的鏈且更優。那么就要處理環上每個點入邊的最大值和次大值之差,以此為權值斷掉最小的邊。

注意判斷一開始就強連通的情況(小心 \(\rho\) 形環)。

T3

每個點肯定是要分兩個方向拆點的。

可以再圖上直接拓撲 DP,成環的位置遍歷不到就是 \(-1\),其它部分便是 DAG,用 \(\texttt{std::bitset}\) 處理能到達每個點的點集,復雜度 \(\mathcal O(\frac{n^4}{\omega})\),滿數據 \(3.2\mathrm s\)。空間開不下,但是任意時刻在隊列里的點是 \(\mathcal O(n)\) 級別的,垃圾回收即可。

更優秀的。基於網格圖的特殊性我們知道到達一個點必須要到達某兩個前驅點,那么一行一行按順序進行記憶化搜索,繼承左邊的點的答案,dfs 新增的點集,\(\mathcal O(n^3)\)

T4

首先先染再折是最優的,並且只用需要染兩種顏色。

每次折疊操作可以做到的是:

  • 選一個一個分界點,較短一端刪去,分界點所在連通塊折半,放在邊界;
  • 邊界連通塊長度減一;

可以發現邊界連通塊是任意改變長度的,而中間的連通塊只有長度為偶數時才有機會折半放到邊界。容易除了邊界以外的連通塊長度為偶數是可行的充要條件。

一個偶數連通塊一定可以拆成若干 2 連通塊,如果我們需要最后包含顏色 \(c\),每個包含 \(c\) 的 2 連通塊需要全染成 \(c\),其他連通塊,其他 2 連通塊只要染成剩余部分出現次數最多的顏色。

那么對於每種顏色,我們枚舉中間連通塊的起始位置,每次對一個顏色的數量增減 1,可以用桶動態維護出現次數最多的顏色。


9.19

T1

不考慮背包的限制,就是二維偏序。我們只要保證二維偏序的每一個狀態都是合法的,也就能夠讓最后每個物品都能對應至少一個背包。

每個背包作用的范圍是一個前綴,按體積從小到大做是困難的,因為當前物品是否占用背包會影響后續物品。那么可以從后往前做二維偏序,可以容易地判斷當前狀態的物品數是否超出限制,和限制取 \(\min\) 即可(較少的物品數是一定能達到的)。

T2

\(f(d,i)\) 表示高度至多為 \(d\)\(i\) 個點的合法樹方案數,答案可以對 \(f(d,n)\) 差分得到。

轉移考慮對於根合並若干子樹:根一定是編號最小的;剩下的子樹互相獨立,屬於有標號集合的合並;為了避免子樹合並順序造成重復,每次令新加入的子樹的根為當前編號最小的點即可。

復雜度 \(\mathcal O(n^3)\)。可以 NTT 優化二項卷積到 \(\mathcal O(n^2\log n)\)

T3

題面太過分了。

一個子串是合法的當且僅當用棧做一遍后棧高為 \(0\),因為“凹”的可以交換一對字母的出入棧變成“凸”,棧高某一時刻 \(< 0\) 是沒關系的。

然后哈希一下當前棧的狀態統計一下。

T4

通分一下就是要找一對點 \((x_1,y_1),(x_2,y_2)\) 使得 \(\displaystyle\left|\frac{(Px_1-Qy_1)-(Px_2-Qy_2)}{Qx_1-Qx_2}\right|\) 最接近 \(0\)

變換坐標為 \((Qx,Px-Qy)\),那么就是找到斜率最接近 \(0\) 的直線,一定產生於縱坐標最接近的點對,按縱坐標排序就可以了。


9.22

時間不太夠。

T1

討論一下 AAA, AAB, ABC 三種情況。每次枚舉兩個數,求逆后用 \(\texttt{std::map<>}\) 找第三個數。

T2

查詢子樹中值域范圍內的點權和,放到 dfs 序上,主席樹。

T3

二叉搜索樹一個子樹是一個區間,那么做區間 DP。對於區間枚舉子樹的根,發現子樹的根的父親只有兩個選擇,每個區間只需要記兩個狀態用於轉移。

T4

賽時不會貪心,寫個線段樹優化建圖然后跑 Dinic 最大流混了 70 分,后來拉個 HLPP 的板子直接過了。/jy

貪心。按照距一端的距離從小到大排序,讓每個座位貪心地去匹配能到達它並且 \(s\) 最小的人。

另一端也是一樣。

T5

模擬,沒補呢。

T6

首先一個區間被另一個區間包含的話,這個小區間就是無用的。

此時一個區間作用的一定是序列上連續的一段,否則不優,所以只需要划分序列,令權值最大。處理每個點可划分為同一段的點的范圍,\(\mathcal O(n^2)\) DP 即可。


9.24

T1

二分然后最短路,單調性感性理解。

T2

我們要求 \(\sum_{1\le 2i-1\le n}(2i-1)\times 9\times 10^{i-1}\)

拆開式子 \((2i-1)\times 10^{i-1}\) 發現是可以用 \(10^{i-1}\)\((i-1)10^{i-1}\) 表示的,矩陣快速冪。

更為優秀的做法是仔細推式子:

\[f(i)=\sum_{i=1}^{n'}(2i-1)\times 10^{i-1} \]

類似等比數列求和,裂項相消,

\[\begin{aligned} 10f(i)-f(i)=&\left(\sum_{i=2}^{n'+1}(2i-3)\times 10^{i-1}\right)-\left(\sum_{i=1}^{n'}(2i-1)\times 10^{i-1}\right)\\ &=(2n'-1)\times 10^{n'}-2\sum_{i=1}^{n'-1}10^i-1\\ &=(2n'-1)\times 10^{n'}-\frac 2 9(10^{n'}-10)-1\\ \end{aligned} \]

\(9\)\(233333\) 互質,可以 exgcd 求逆元。

T3

裸搜都跑不了 \(0.01\mathrm s\)

T4

裸的動態 DP。


9.25

T1

線性做法慘遭卡常,夢想選手白拿 45。

對於每個連通塊,如果確定一個點的值,可以通過 dfs 樹推出其他點的值。

那么將這個點設為未知量,將其他點都表示成關於這個點的一次函數,dfs 過程中用反祖邊判斷是否矛盾,用每個點的取值范圍更新未知量的取值范圍。

最后所有點的總和也是關於未知量的一次函數,可以根據范圍直接求最值。

T2

轉化題意為求出每個點左下方單調棧的大小。

按橫座標從小到大做,用線段樹在縱坐標上維護區間的單調棧。類似樓房重建,不顯式地維護,只記錄單調棧左右兩端。合並兩個單調棧,就在左邊的子樹二分出左單調棧第一個彈出的位置。

或者 CDQ 分治,y 坐標上考慮左區間對右區間的貢獻的時候,以 x 為權值左右分別維護單調棧,然后每次在左單調棧二分第一個彈出的位置。

都是 \(\mathcal O(n\log^2n)\)

T3

去掉 CEO 的領帶后,貪心的策略是排序后排名相同的配對最優,因為此時最大值移動位置不會變得更優。

T4

每道菜需要至少 \(k\) 個人,那么可以讓這 \(k\) 包括貢獻 \(1\) 單位時間(記為基礎時間),然后剩余的隨意分配。

那么也就是我們要選出若干個人,時間總和 \(\ge \sum{a_i}\) 並且基礎時間總和 \(\ge nk\),同時最小化時間總和。

最小化時間總和的話,我們盡量讓每個人做的菜盡量多,貢獻的基礎時間一定是 \(\min(n,b_i)\)

時間總和有下界又需要盡量小,這是需要具體記進 DP 狀態的。

做背包,以時間 \(b_i\) 為體積,貢獻的基礎時間 \(\min(n,b_i)\) 為價值。最后答案就是基礎時間總和 \(\ge nk\) 的最小的背包。\(\mathcal O(m\sum b_i)\)

注意判一堆無解情況。


9.27

T1

建出虛樹,然后對每條邊代表的樹鏈用重鏈剖分查詢,主席樹維護 dfs 序上區間的權值集合即可。復雜度 \(\mathcal O(\sum k\log^2n)\)

后來發現求 \(\min\) 的話不需要建虛樹,只要求出虛樹深度最小的點,把每條葉子到該點的鏈的答案並起來就好了,直接在樹上建主席樹,除了 LCA 以外不需要樹剖,會好寫很多,就是 \(\mathcal O(\sum k\log n)\) 了。

T2

括號序列考慮放到網格圖上向上或向右走的路徑。

給出了一段路徑,那么只要 \(\mathcal O((n-m)^2)\) 枚舉這一段的起點,注意判一下結尾是否超出邊界或者超過直線 \(y=x\),然后翻折法計算開頭結尾兩部分。

T3

\(+1\) 操作有進位難以處理,觀察到性質:\(200 < 2^8\)\(n\)\(+1\) 操作的進位至多影響低 \(8\) 位。

那么考慮狀壓低 \(8\) 位的狀態,\(8\) 位以上只要記最低的連續段的顏色和長度。

可能會有低 \(8\) 位全是 \(1\) 然后 \(+1\) 進位,但是至多會發生 \(1\) 次,所以 \(8\) 位以上只用考慮 \(1\) 連續段變 \(0\),而不用考慮第一個 \(0\)\(1\) 然后和前面的 \(1\) 連續段接上的問題。

復雜度 \(\mathcal O(n^22^8)\)

T4

大模擬,不會,先咕。


9.29

今天太困了!睡到十點半才開始寫,能混到 490 分也是服了。

T1

每次詢問判斷每個關鍵點是否在鏈上,然后各種模擬,細節題。

T2

略。

T3

首先 \(a_i\) 遍歷的數是 \(\gcd(a_i,n)\) 的倍數。

那么一個數 \(k\) 能被遍歷的充要條件是 \(\exists a_i,\gcd(a_i,n)|k\),也就是 \(\gcd(a_i,n)|\gcd(k,n)\)。那么讓 \(k\)\(\gcd(k,n)\) 處恰好被計算一次。

枚舉 \(n\) 的約數 \(d\),如果 \(\exists a_i,\gcd(a_i,n)|d\),那么 \(d\) 會對所有 \(\gcd(k,n)=d\)\(k\) 產生貢獻。其數量為 \(\varphi(\frac nd)\)

指數級的暴力容斥剪剪枝也是可以過的。

T4

去重麻煩,轉化為最小化未打中的鳥數量。

從前往后不斷加入線段,線段樹維護區間加、區間最小值,用於 DP 轉移。

T5

如果若干個環覆蓋了 \(26\) 個字母會無解,這題很不嚴謹。

T6

Dilworth 引理。


九月份結束了。


免責聲明!

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



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