IOI 2020 集訓隊作業胡扯「51, 100」


IOI 2020 集訓隊作業胡扯「1, 50」
IOI 2020 集訓隊作業胡扯「51, 100」(★)
IOI 2020 集訓隊作業胡扯「101, 150」

如果您點擊了某個超鏈接,但是並沒有發生任何變化,這意味着您可能需要在另外兩章節中尋找對應內容。

表格

試題一 完成情況 試題二 完成情況 試題三 完成情況
cf549E cf674G arc103_f
cf594E agc034_f agc030_d
cf575E agc035_c agc026_f
cf607E agc038_e agc030_c
cf611G agc034_d agc024_f
cf571E cf696F arc093_e
cf573E cf704E arc103_d
cf627F agc035_d agc033_f
cf538G cf674D arc101_f
cf566C cf700E arc092_f
cf566E agc034_e agc022_d
cf613E agc033_e agc021_f
cf528C agc038_f agc029_e
cf611H agc036_d agc027_e
cf626G cf666D arc102_f
cf605E agc031_e agc028_d
cf536D agc027_f agc024_e
cf553E agc037_f agc029_c
cf571D cf708E arc093_f
cf603E agc036_e agc021_e
cf590E agc031_d agc026_e
cf587F cf685C arc096_e
cf587D cf674F arc091_f
cf575I agc035_f agc028_f
cf504E cf671E arc101_e
cf585F cf708D arc095_f
cf521D agc036_f agc028_c
cf585E agc032_c agc023_f
cf568C cf666E agc025_e
cf568E cf704C arc100_f
cf538H agc032_d agc024_d
cf582E agc039_e agc025_f
cf526F agc037_d agc020_e
cf521E agc030_f agc026_d
cf526G cf698D arc089_f
cf582D cf634F agc020_d
cf578F cf704B arc099_f
cf578E agc035_e agc025_d
cf516E agc030_e agc027_d
cf576E cf704D arc096_f
cf547E cf671D arc097_f
cf547D agc033_d agc031_f
cf575A cf639E agc039_f
cf559E agc037_e agc020_f
cf512D agc028_e agc022_f
cf506E cf639F agc039_d
cf576D agc029_f agc022_e
cf555E agc032_e agc023_d
cf506C cf679E arc098_f
cf516D agc032_f agc023_e

的表示主要沒看題解,的表示主要看了題解。


2020-01-15

agc020_e

等價於計算有多少個編碼方式,解碼后能得到 \(S\) 的子集。

假設長度為 \(n\) 的字符串 \(s\) 的答案為 \(f(s)\),則可以列出兩種轉移方式:

  1. \(f(s) =_+ f(s[1 : n - 1]) \times (1 + s[n])\)
    表示:編碼方式的最后一個字符為 01,去掉這個字符后,前面的方案數即為 \(f(s[1 : n - 1])\)
    而當 \(s[n] = 0\) 時,最后的字符只能填 0,有 \(1\) 種方案;否則可以填 01,有 \(2\) 種方案。

  2. \(f(s) =_+ f(s[1 : n - li]) \times f(\bigcap_{j = 1}^{i} s[n - lj + 1 : n - l(j - 1)])\)\(i \ge 2\)\(l \ge 1\)\(li \le n\))。
    表示:編碼方式的最后一個字符為 ),也就是說最后一段是 (\(t\)x\(i\)),枚舉長度 \(l = |t|\) 和重復次數 \(i\)
    后面的 \(t\) 需要滿足解碼后是 \(s\) 中最后 \(i\) 段長度為 \(l\) 的子串的交的子集,也就是 \(\bigcap_{j = 1}^{i} s[n - lj + 1 : n - l(j - 1)]\) 的子集。

你可能會認為這樣子時間復雜度太大,但是題解告訴我們,記憶化搜索后,有用的狀態數是 \(\mathcal O (2^{|S| / 8} + {|S|}^3)\) 的。每個狀態可以花 \(\mathcal O (n^2)\) 的時間進行轉移,反正就是跑過了。

時間復雜度為 \(\mathcal O ({|S|}^2 2^{|S| / 8} + {|S|}^5)\)評測鏈接

cf566C

注意到 \({|x|}^{1.5}\) 是下凸函數,也就是說每個位置都可以求出向最優解方向移動的傾向,也就是導數。

考慮點分樹,從根開始利用導數的正負確定應該往哪個子樹方向走,最多走 \(\log n\) 層。

不需要顯式建出點分樹。

時間復雜度為 \(\mathcal O (n \log n)\)評測鏈接

2020-01-16

cf587F

這題和 cf547E 極其相似,那題是問 \(s_k\)\(s_{l \sim r}\) 中的出現次數,這題是問 \(s_{l \sim r}\)\(s_k\) 中的出現次數。

\(\displaystyle \sum_{i = 1}^{n} |s_i| = l\),有 \(l = \Omega (n)\)

先建出 AC 自動機,然后考慮一下答案如何表示。

\(\mathrm{id}_{i, j}\)\(s_i[1 : j]\) 在 AC 自動機上對應的節點。
特別地,\(\mathrm{id}_i = \mathrm{id}_{i, |s_i|}\)\(s_i\) 在 AC 自動機上對應的節點。

則詢問 \((l, r, k)\) 的答案可以表示為:
令 fail 樹中的 \(\mathrm{id}_{l \sim r}\) 的子樹的權值都加上 \(1\)(重復的加多次)。
則答案為 \(\mathrm{id}_{k, 1 \sim |s_k|}\) 的權值和。

還以為和 cf547E 一樣能有簡單做法,結果想了半天都沒想到 \(\mathrm{polylog}\) 的做法,看了一下題解發現是根號的。

考慮根號分治,\(|s_k| \le T\) 的和 \(|s_k| > T\) 的詢問分開處理。

對於 \(|s_k| > T\) 的串,這樣的串不會超過 \(l / T\) 個,考慮對於每個串使用線性的時間處理:
先把 \(\mathrm{id}_{k, 1 \sim |s_k|}\) 的權值定為 \(1\),然后在 fail 樹上做一遍子樹和,求出每個點子樹中的權值和。
然后對於關於 \(s_k\) 的所有詢問,拆分左右端點並按升序排序,用一個指針掃過所有詢問端點,並用 \(\mathrm{id}_i\) 的權值累加答案。
這一部分的時間復雜度為 \(\mathcal O (l^2 / T)\)

對於 \(|s_k| \le T\) 的串,每個詢問考慮用 \(\mathcal O (|s_k|)\) 的時間進行處理:
對於每個詢問拆分左右端點並按升序排序,用一個指針掃過所有詢問端點,每處理一個,就把 fail 樹上 \(\mathrm{id}_i\) 的子樹的權值都加上 \(1\)
對於每個詢問 \(s_k\),查詢 \(\mathrm{id}_{k, 1 \sim |s_k|}\) 當前的權值並累加,就是該詢問的答案。
子樹加,單點查使用 DFS 序 + 分塊實現(\(B = \sqrt{l}\)),這一部分的時間復雜度為 \(\mathcal O (n \sqrt{l} + qT)\)

\(T = \Theta (l / \sqrt{q})\) 可以取得最佳時間復雜度。

時間復雜度為 \(\mathcal O (n \sqrt{l} + q + l \sqrt{q})\)評測鏈接

2020-01-27

cf571E

記集合 \(\{a, a b, a b^2, a b^3, \ldots \}\)\(\langle a, b \rangle\),特別地,記 \(\{a\}\)\(\langle a, 1 \rangle\)

考慮合並 \(\langle a, b \rangle\)\(\langle c, d \rangle\),形成新的集合,可以證明這個集合也可以表示成等比數列形式。

令所有 \(n\)\(a, b\) 中涉及到的質數的集合為 \(P\),則可以把 \(a, b, c, d\) 表示為 \(|P|\) 維向量(第 \(i\) 個分量的大小為第 \(i\) 個質數在數值的質因數分解中的冪次)。

也就是要解 \(\vec{a} + k_1 \vec{b} = \vec{c} + k_2 \vec{d}\),其中 \(k_1, k_2\) 是非負整數。

考慮 \(\vec{b}\)\(\vec{d}\) 是否為零向量,以及是否線性相關。

如果至少一個為零向量,可以直接判斷,如果不線性相關,可以解二元一次方程組,如果線性相關,需要解線性同余方程。

大分類討論即可。

時間復雜度為 \(\mathcal O (n^2 \omega(v) \log v)\),其中 \(v\) 是值域,\(\omega(n)\) 表示小於等於 \(n\) 的正整數的不同質因數個數的最大值,評測鏈接

2020-01-28

cf590E

學習了一下偏序集上的最長反鏈求法。

\(l\) 為字符串長度之和。

先構造 AC 自動機,然后可以在 \(\mathcal O (l)\) 的時間內求出每個串在每個結束位置包含的最長的小串是哪一個。

注意這並不是全部的包含關系,所以還要用 Floyd 求出傳遞閉包,用 bitset 優化。

然后是偏序集上求最長反鏈(求方案),參考 [CTSC2008]祭祀river 的做法。

代碼中使用了 Dinic 求二分圖匹配。

時間復雜度為 \(\displaystyle \mathcal O \!\left( l + \frac{n^3}{w} + n^{2.5} \right)\),其中 \(w\) 為字長,評測鏈接

2020-01-29

agc028_c

與其設置 \(x \to y\) 這條邊的權值為 \(\min(A_x, B_y)\),我們看成有兩條邊,權值分別為 \(A_x\)\(B_y\)。這樣轉化后,答案仍然相同。

我們考慮某種最終答案,假設走了 \(x \to y\) 這條邊,
如果走的是權值為 \(A_x\) 的邊,我們把這條邊染紅色
如果走的是權值為 \(B_y\) 的邊,我們把這條邊染藍色

也就是說,紅色邊的邊權等於它的起點的 \(A_x\)藍色邊的邊權等於它的終點的 \(B_y\)

我們考慮最終的答案形成的環,要么全是邊,要么全是邊,要么交替。

這不是廢話嗎?為什么要分三類?

這是因為只有交替,才能夠允許同時存在「入邊和出邊都是紅色的點」和「入邊和出邊都是藍色的點」。
也就是說,當且僅當交替時,才能任意選入邊和出邊的顏色,如果不是交替的,則顏色必須完全一樣。

那么我們先讓答案變成全選紅色和全選藍色\(\min\),也就是 \(\sum A_i\)\(\sum b_i\)\(\min\)

然后考慮交替時的答案怎么計算:

因為交替時,必然會出現入邊為藍色,出邊為紅色的點。我們枚舉這樣的一個點 \(i\) 之后,把它的 \(A_i\)\(B_i\) 都加進答案,只要在剩余的 \(2n - 2\)\(A_j\)\(B_j\) 中,選出最小的 \(n - 2\) 個,就一定能夠組成合法的答案。

把標號和權值一起記下來排序,就能得到每個點的 \(A_i\)\(B_i\) 的排名,分類討論一下不難得到答案。

時間復雜度為 \(\mathcal O (n \log n)\)評測鏈接

2020-01-30

arc097_f

我們的目標是把所有白點變黑。首先,特判掉沒有白點,或者白點只有 \(1\) 個的情況。分別輸出 \(0\)\(1\)

我們記 \({col}_i\) 為點 \(i\) 的顏色,如果點 \(i\) 為白色,則 \({col}_i = 1\),否則 \({col}_i = 0\)

剩下的情況中,我們把包含所有白點的極小連通塊抽離出來(可以通過不斷刪除黑色葉子實現)。
顯然,這個連通塊形成了有 \(\ge 2\) 個點的一棵樹。令連通塊中的點數為 \(num\)

不難發現,最優解中,貓一定不會踏出這個連通塊。
但是又必須經過連通塊內的每個點(因為必須經過連通塊里的所有葉子,連通塊中的所有葉子都是白點)。

那么接下來,我們只考慮這個連通塊,定義 \({deg}_i\) 為連通塊中點 \(i\) 的度數(不考慮原樹中的邊)。

又有結論:貓不會經過一條邊 \(\ge 3\) 次,也就是說只會經過 \(1\) 次或 \(2\) 次。
(這是因為多余的操作都可以簡化成“改變當前點的顏色”的操作,一定不會更劣)

我們先假設:貓必須回到起點。

可以發現這時貓的起點對答案已經沒有影響了。因為每條邊都會被正向反向分別經過恰好 \(1\) 次。

也就是說,先規划好了路線,計算這個路線對點顏色的影響。在這之后再“插入”改變當前點顏色的操作。

那么顯然,在這個情況下,如果 \({deg}_i\) 為奇數,則 \({col}_i\) 就會因為該點被到達了奇數次而發生改變,否則 \({col}_i\) 保持不變。

最終,答案就等於 \(2 \cdot (num - 1) + \sum {col}_i\),也就是 \(2\) 乘邊數,加上 \({col}_i = 1\) 的點數,這些點需要額外使用一次操作。

問題在於:貓不一定要回到起點。

假設貓從 \(x\) 出發,最終到達了 \(y\)。令 \(x\)\(y\) 之間的邊數為 \(len\)

則可以少走 \(len\) 條邊,也就是不用從 \(y\) 再返回 \(x\) 了。

但是少走的這 \(len\) 條邊,對 \(col\) 也有影響:
因為從 \(y\) 返回 \(x\) 的邊少走了,所以 \(x\)\(y\) 路徑上的點(除了 \(y\) 本身)的 \(col\) 都會發生變化。

實際上恰好有 \(len\) 個點的 \(col\) 發生了變化。
如果 \(col\)\(1\) 變成了 \(0\),可以少花一次操作。但是從 \(0\) 變成 \(1\) 的話,就要多花一次操作。

也就是說,平均算下來,如果原先的 \(col\)\(1\),可以少花兩次操作;如果是 \(0\),則不虧不賺。

總的來說,就是這條路徑,經過的 \({col}_i = 1\) 的點要盡量多(但是不包含終點)。

一個觀察:葉子的 \(col\) 始終為 \(0\)(因為原先葉子的 \(col = 1\),但是葉子的 \(deg\) 也是 \(1\),所以抵消了)。

而這條路徑自然是越長越好,肯定會延伸到葉子,所以包不包含終點也沒有影響了。

樹形 DP 計算經過的 \({col}_i = 1\) 的點最多的路徑就行了。

假設最多經過 \(ans\)\({col}_i = 1\) 的點,則最終答案為 \(2 \cdot (num - 1) + \sum {col}_i - 2 \cdot ans\)

時間復雜度為 \(\mathcal O (n)\)評測鏈接

agc030_d

因為 \(N\) 很小,考慮直接枚舉位置對 \(\langle i, j \rangle\)\(1 \le i < j \le N\))以統計逆序對。

考慮一個概率 DP:令 \(f(i, j)\)\(1 \le i, j \le N\))為當前時刻下\(A_i > A_j\) 的概率。
(這里假設對於 \(Q\) 個操作,每個操作都以 \(1 / 2\) 的概率執行)

那么最終時刻下,滿足 \(i < j\)\(f(i, j)\) 之和,再乘以 \(2^Q\) 就是答案(期望的線性性)。

按順序考慮每個時刻(操作),考慮新的 \(f(i, j)\) 和原先的比有什么變化。

可以發現只有 \(\mathcal O (N)\) 個位置會發生變化。具體地說,只有 \(i, j\) 有至少一個等於 \(X_i\)\(Y_i\) 時才有可能發生變化。

暴力轉移即可。

時間復雜度為 \(\mathcal O (N (N + Q))\)評測鏈接

arc093_e

考慮原圖的一棵生成樹 \(T\),邊權和為 \(S\)

對於一條非樹邊 \(e\),定義 \(v(e)\)\(W_e\) 減去「\(U_e, V_e\)\(T\) 上的路徑上的最大邊權」。

也就是說,\(v(e)\) 表示用 \(e\) 替換 \(T\) 中的一條邊,形成新的生成樹的最小代價。顯然有 \(v(e) \ge 0\)

假設染色方案已確定,如何計算滿足條件的最小生成樹?

  • 如果 \(T\) 中的邊不同色,則 \(T\) 就是合法的最小生成樹,權值為 \(S\)
  • 否則 \(T\) 中的邊都是同一種顏色,取 \(v(e)\) 最小的異色的 \(e\),則合法的最小生成樹的權值為 \(S + v(e)\)
  • 如果不存在這樣的 \(e\)(所有邊全部同色),則不存在合法的生成樹。

那么答案就很顯然了,先把 \(X\) 減去 \(S\)

如果 \(X < 0\),則無合法解,輸出 0

如果 \(X > 0\),則 \(T\) 必須同色,且 \(v(e) < X\) 的邊都必須染相同顏色,\(v(e) = X\) 的邊必須至少有一個染不同顏色。

如果 \(X = 0\),則是上面的答案的基礎上,再加上 \(T\) 不同色,其它邊任意選的方案數。

容斥一下答案就出來了。

時間復雜度為 \(\mathcal O (M \log M)\)評測鏈接

2020-02-01

agc024_d

觀察樣例,再自己手造幾組數據,就可以發現,最終長成的樹必然是:

  1. 以一個點為中心的放射狀。
  2. 以一條邊為中心的放射狀(兩側對稱)。

更具體地說,也就是把中心點或中心邊「拎起來」,下面掛着的樹形態,滿足每個深度相同的子樹都完全一致。

而這時,答案就為樹的深度(假設中心點的深度為 \(1\),中心邊的兩端點深度為 \(1\))。

而葉子個數,就等於每一個深度的節點的,子節點個數的乘積(包括深度 \(1\),但不包括葉子所在的深度)。

那么我們枚舉中心點,或者中心邊,把原樹「拎起來」,原樹就變成了一個奇怪的形狀。

那么顯然我們需要補最少的點,對於每個深度,把子節點個數取 \(\max\) 再相乘,就得到最終的最少葉子個數了。

每個點和邊都枚舉一遍,取最優解。

時間復雜度為 \(\mathcal O (n^2)\)評測鏈接

arc091_f

這題真的好簡單……

顯然我們求一下每堆石子的 SG 函數就好了。

我們打表找規律,當 \(K = 1\) 的時候,就是普通的 Nim。如果 \(K \ge 2\) 會怎么樣?

\(K = 4\) 為例:

\[\begin{bmatrix} 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 & 15 & 16 & 17 & 18 & 19 & 20 & 21 & 22 & 23 \\ \hline 0 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 2 & 1 & 0 & 2 & 3 & 1 & 0 & 2 & 4 & 3 & 1 & 0 & 5 & 2 & 4 & 3 \end{bmatrix} \]

不難發現規律:

\[\operatorname{SG}_k(n) = \begin{cases} 0 & , 0 \le n < k \\ n / k & , n \ge k \wedge n \bmod k = 0 \\ \displaystyle \operatorname{SG}_k \!\left(n - \!\left\lfloor \frac{n}{k} \right\rfloor\! - 1 \right) & , n \ge k \wedge n \bmod k > 0 \end{cases} \]

然而直接這樣算有點慢,不難發現,如果按照 \(\displaystyle \left\lfloor \frac{n}{k} \right\rfloor\) 分段,則每一段內是循環的。

可以把第三行改寫成:\(\displaystyle \operatorname{SG}_k \!\left( n - \!\left\lfloor \frac{\displaystyle n - \!\left\lfloor \frac{n}{k} \right\rfloor\! \cdot (k - 1)}{\displaystyle \left\lfloor \frac{n}{k} \right\rfloor\! + 1} \right\rfloor\! \cdot \!\left( \left\lfloor \frac{n}{k} \right\rfloor\! + 1 \right) \right)\)

這樣子計算,可以證明會在 \(\sqrt{n}\) 次內結束。

時間復雜度為 \(\mathcal O (N \sqrt{A})\)評測鏈接

2020-02-02

agc035_c

\(N\)\(2\) 的次冪時無解,這是因為 \(N\) 的最高位無法被異或得到。

否則一定有解,構造如下(令 \(m\) 為小於等於 \(N\) 的最大的 \(2\) 的次冪,\(k\)\(N - m\)):

\(N\) 是偶數時才需要連 \((m+1) \leftrightarrow N\)\(k \leftrightarrow N'\)

時間復雜度為 \(\mathcal O (N)\)評測鏈接

2020-02-03

cf603E

考慮給定了邊集后,如何判斷是否存在合法的選邊方案。

容易證明存在一種方案,當且僅當每個連通塊的大小都是偶數。
(考慮每個連通塊僅保留一棵生成樹,再在生成樹上自底向上選邊)

所以先把 \(n \bmod 2 \ne 0\) 的情況判掉(全部輸出 -1)。

那么相當於每次我們可以嘗試不斷把權值最大的邊刪去,使得刪去后圖的每個連通塊大小仍為偶數。

加邊刪邊時,使用 LCT 維護最小生成樹即可。

判斷一條邊是否需要刪除,需要用能夠統計虛子樹信息的 LCT,這里虛子樹信息就是子樹大小。

為了方便考慮,代碼中在初始的時候就加上了 \(n / 2\) 條邊,第 \(i\) 條連接 \(2i - 1\)\(2i\),權值為 \(\infty\)
這樣做可以保證在一開始的時候每個連通塊大小都是偶數,省去了不必要的特判,如果算出來答案為 \(\infty\),就輸出 -1

時間復雜度為 \(\mathcal O (m \log m)\)評測鏈接

2020-02-04

agc034_e

既然所有棋子最終到達了同一個點,我們先考慮枚舉這個點,記做 \(r\),以 \(r\) 為根建樹。

\(s_i\) 表示 \(i\) 子樹中的所有點 \(A_i\) 之和,也就是子樹中的棋子個數;
\(w_i\) 表示 \(i\) 子樹中的所有棋子到 \(i\) 的距離之和。

這樣,\(s_i\)\(w_i\) 都可以很容易地計算。
(具體地說,\(\displaystyle w_u = \sum_{v \in \mathrm{sons}_u} w_v + s_v\)

考慮做題目中的操作會帶來的影響,假設操作的棋子分別位於 \(x, y\)

  1. \(x, y\) 為祖孫關系。這個操作對 \(r\) 本身,以及 \(r\) 的任意一個子樹方向\(w\) 值都不會產生影響(注意不是子樹,而是這個子樹對 \(w_r\) 產生的貢獻)。
  2. \(x, y\)\(r\) 的不同子樹中。這個操作會使 \(r\) 的那兩個子樹方向的 \(w\) 值各減去 \(1\)
  3. \(x, y\)\(r\) 的同一個子樹中,但是不為祖孫關系。這個操作會使 \(r\) 的那一個子樹方向的 \(w\) 值減去 \(2\)

可以發現:如果 \(w_r\) 為偶數,在所有子樹方向的貢獻中,最大的那一個,也不超過 \(w_r\) 的一半的話,就可以不斷通過 2 操作把某兩個子樹方向的貢獻減去 \(1\),最終使得 \(w_r\) 變成 \(0\)。也就意味着所有棋子都到達了 \(r\)。(具體方法是,每次都選擇當前貢獻最大的子樹中的一個棋子進行操作)

但是如果貢獻最大的那個子樹,它的貢獻超過了 \(w_r\) 的一半怎么辦呢?這時就需要在這個子樹中使用 3 操作以減小這個子樹的貢獻。可以發現這個貢獻減得越小越好。

這啟發我們定義 \(f_i\) 表示只操作 \(i\) 子樹中的棋子,能夠把 \(w_i\) 最小減少到多少。就是做操作后 \(w_i\) 的最小值。

這樣一來,只要 \(f_r = 0\),就意味着可以把棋子都聚集到 \(r\) 上,且根據上面的過程,恰好花費 \(w_r / 2\) 步。
(因為沒必要使用 1 操作,而 2, 3 操作都會讓 \(w_r\) 減去 \(2\)

我們考慮遞歸地計算 \(f_i\)。要求 \(f_u\) 時,考慮 \(u\) 的每個子節點 \(v\)\(w_v\)\(f_v\)
同樣地,考慮對 \(w_u\) 貢獻最大的那個子樹 \(v\),我們使用 3 操作,讓它的 \(w_v\) 變成了 \(f_v\)
這樣一來,若 \((f_v + s_v) \le w_u / 2\),則 \(f_u = w_u \bmod 2\),否則 \(f_u = (f_v + s_v) - (w_u - (w_v + s_v))\)

這樣就可以在 \(\mathcal O (N)\) 的時間內計算最終聚集到點 \(r\) 的答案了。總時間復雜度為 \(\mathcal O (N^2)\),足以通過該題。

顯然這個式子是可以換根 DP 的,所以代碼中也就寫了,時間復雜度變為 \(\mathcal O (N)\)

時間復雜度為 \(\mathcal O (N)\)評測鏈接

agc026_d

去年 CSP 前,做過一個比賽,出題人搬了這題,我打了一整場比賽把它切掉了,其他題沒分(
PS:數據范圍改成了 \(1 \le N \le {10}^5\)


注意:我的做法與題解的做法有較大出入。

我們首先考慮這樣的 DP:令 \(dp(i)\) 表示前 \(i\) 列已經染色,其他列還未染色的方案數。
但是這樣定義的狀態是沒法轉移的。

為什么?我們先考慮一下轉移的方式:

  1. 如果相鄰的兩個格子為同種顏色(#### 或豎着排列的),則它們所在的 \(2 \times 2\) 區域中的顏色將被唯一確定。
    ##
    ##
    ##
    ##
    或它們旋轉 \({90}^{\circ}\) 的結果。
  2. 如果相鄰的兩個格子的顏色不同(#### 或豎着排列的),在不考慮其它限制的情況下,它們所在的 \(2 \times 2\) 區域中的顏色是有兩種方案的。
    ##
    ##
    或其旋轉 \({90}^{\circ}\) 的結果。

現在,考慮前 \(i - 1\) 列已經染色,第 \(i\) 列以及之后還未染色的情況。
那么第 \(i\) 列的染色情況,可以只由第 \(i - 1\) 列的染色情況確定。
下面舉幾個例子(假設第一列為第 \(i - 1\) 列,第二列為第 \(i\) 列):

  1.  ?
     ?
    #?
    #?
    #?
    #?
    #?
    #?
    ,這個情況下第 \(i\) 列有 \(8\) 種染色方案:最底下 \(6\)\(2\) 種,上面兩個格子 \(2 \times 2 = 4\) 種。
  2.  ?
     ?
    #?
    #?
    #?
    #?
    #?
    #?
    ,這個情況下第 \(i\) 列有 \(4\) 種染色方案:最底下 \(6\)\(1\) 種,上面兩個格子 \(2 \times 2 = 4\) 種。
  3. #
    #
    #?
    #?
    #?
    #?
    #?
    #?
    ,這個情況下第 \(i\) 列有 \(2\) 種染色方案。
  4. #
    #
    #?
    #?
    #?
    #?
    #?
    #?
    ,這個情況下第 \(i\) 列有 \(1\) 種染色方案。

可以發現,關鍵就在於第 \(i - 1\) 列的,最靠下的,上下相鄰兩個格子顏色相同的位置。
如果這個位置在第 \(i\) 列的范圍內,則第 \(i\) 列的最底下 \(\min(h_{i - 1}, h_i)\) 個格子的顏色就會被唯一確定,否則恰有兩種方案。
剩下 \(\max(h_i - h_{i - 1}, 0)\) 個格子可以任意染色。

可能可以考慮記狀態 \(dp(i, j)\) 表示前 \(i\) 列已經染色,且第 \(i\) 列最靠下的上下相鄰兩個格子顏色相同的位置為 \(j\)
但是這樣狀態也太多了,也沒法做。

最后我們考慮記狀態 \(dp(i)\) 表示:前 \(i\) 列已經染色,且保證第 \(i\) 列任意兩個相鄰格子的顏色都不同的方案數。
也就是第 \(i\) 列顏色交錯的方案數。這樣令 \(h_{n + 1} = 1\),則 \(dp(n + 1) / 2\) 就是答案。

我們考慮轉移,如果 \(h_{i - 1} \le h_i\),也就是第 \(i\) 列變高了,則 \(dp(i) = 2 \cdot dp(i - 1)\)
這是因為我們限制了第 \(i\) 列是交錯的,又因為 \(h_{i - 1} \le h_i\),所以第 \(i - 1\) 列也必然是交錯的,可以直接轉移。

但是如果 \(h_{i - 1} > h_i\) 怎么辦?這時限制第 \(i\)交錯,不能保證第 \(i - 1\) 列也是交錯的。

先小結一下:可以發現,如果第 \(x\) 列的最底下 \(w\) 個格子是交錯的,那么對於 \(y = x - 1\)\(x + 1\),也就是 \(x\) 的相鄰列,可以推出第 \(y\) 列的最底下 \(\min(w, h_y)\) 個格子是交錯的。

這引出一個結論:如果第 \(x\) 列是交錯的,則第 \(y\) 列是交錯的充分條件是:對於 \(x \le i \le y\)\(h_i \ge h_y\)
換句話說,就是 \(h_y\)\(x, y\) 之間(包含 \(x, y\))的 \(h\) 的最小值。


回到 DP 上,仍然是要轉移 \(dp(i)\),我們假設前一個一整列都是交錯的列為第 \(j\) 列。

則這個 \(j\) 要滿足 \(\displaystyle h_j < \min_{j < k < i} h_k\),且「\(h_j \ge h_i\) 或『\(h_j < h_i\)\(\displaystyle \min_{j < k < i} > h_i\)』」。

這等價於 \(j\) 是前 \(i - 1\) 列單調棧中的元素(我們維護 \(h\) 值嚴格遞增的單調棧),且當加入 \(i\)\(j\) 被彈棧或 \(j\) 為彈棧后的棧頂(但不能彈出 \(h\) 值恰好等於 \(h_i\) 的元素)。

根據單調棧的結論,總轉移數是 \(\mathcal O (N)\) 的,這是可以接受的。接下來要考慮轉移的系數。


我們首先考慮第一類轉移,也就是 \(j\) 為被彈棧的元素(\(h_j \ge h_i\))的轉移:

我們考慮上圖,\(j = 5\)\(i = 11\)

\(j\)\(i\) 之間的 \(h\) 值依次為 \(6, 10, 11, 8, 12, 10, 3\)

我們已知第 \(j\) 列是交錯的,而之后的每一列都必須不是交錯的。

如果出現了類似圖二中的情況,也就是在“中間部分”(不包括 \(j\)\(i\) 的部分)出現了相鄰兩列顏色沒有翻轉的話,就會導致“中間部分”出現一整列都是交錯的情況,不符合要求。

也就是說“中間部分”必須滿足:每一列的顏色都和上一列的不同,除了最初的那一列(第 \(j + 1\) 列)。
又因為第 \(i\) 列的顏色也可以選擇翻轉或不翻轉,所以這里總共貢獻了 \(2^2 = 4\) 的系數。

考慮圖三圖四的上面的部分,因為不能讓第 \(8\) 列出現一整列都是交錯的情況,需要存在一行的顏色不翻轉,這里有 \(2\) 種情況。
而更上面未染色的部分,每一段紅色的線條都會產生 \(2\) 的貢獻(可以選擇翻轉或不翻轉)。

為什么有恰好 \(2\) 種情況呢?這是因為 \(h_8 - h_j = 8 - 6 = 2\)

這一部分的總貢獻為 \(2^7 + 2^8\),實際上是一個等比數列的形式。
這個等比數列的首項為 \(2^{\mathrm{num1}}\),末項為 \(2^{\mathrm{num2} - 1}\)。總和就為 \(2^{\mathrm{num2}} - 2^{\mathrm{num1}}\)
這里就有 \(\mathrm{num2} = 9\),以及 \(\mathrm{num1} = 7\)

\(\mathrm{num1}, \mathrm{num2}\) 如何計算呢?

我們記 \(b_i\) 表示前 \(i\) 列的形如這樣的紅線個數。可以發現 \(\mathrm{num2} = b_{i - 1} - b_j\),而 \(\mathrm{num1} = \mathrm{num2} - (h_k - h_j)\)
其中 \(k\) 就為上一個被彈棧的元素(這里 \(k = 8\)),也就是滿足 \(j < k\)\(h_k\) 最小的元素之一。

綜上所述,\(j\)\(i\) 產生的貢獻就為 \(4 (2^{\mathrm{num2}} - 2^{\mathrm{num1}})\) 倍的 \(dp(j)\)
(特殊情況是 \(j = i - 1\),因為“中間部分”完全消失了,所以不能套用上面的推導,這時貢獻為 \(2\)


然后我們考慮第二類轉移,也就是 \(j\) 為彈棧后的棧頂,且上一個被彈棧的元素的 \(h\) 值不等於 \(h_i\)

仍然是 \(i = 11\) 的情況,此時 \(j = 2\)

圖二,同樣地我們不能允許出現在“中間部分”的相鄰兩列顏色不翻轉的情況。

特別地,如圖三,我們需要的交錯的高度不是 \(h_j\) 而是 \(h_i\),因為 \(h_i > h_j\)

圖四,可以發現此時顏色不翻轉的行,只有 \(1\) 種取值了,也就是 \(h_3 - h_i = 4 - 3 = 1\)

而上面的部分仍然和前一種情況類似,我們可以求出此時的 \(\mathrm{num2} = b_{i - 1} - b_j - (h_i - h_j)\),而 \(\mathrm{num1} = \mathrm{num2} - (h_k - h_i)\)
其中 \(k\) 的含義和前文相同,為上一個被彈棧的元素。

綜上所述,\(j\)\(i\) 產生的貢獻就為 \(4 (2^{\mathrm{num2}} - 2^{\mathrm{num1}})\) 倍的 \(dp(j)\)
(特殊情況是 \(j = i - 1\),因為“中間部分”完全消失了,所以不能套用上面的推導,這時貢獻為 \(2\)


然而其實我們漏掉了一種情況,要是這樣的 \(j\) 不存在呢?也就是不存在交錯的前一列該怎么辦?

其實這無關緊要,我們只要讓 \(h_0 = 1\),然后設 \(dp(0) = 1\) 就行了,不影響后續計算。

時間復雜度為 \(\mathcal O (N \log \mathrm{MOD})\),其中 \(\log \mathrm{MOD}\) 為快速冪復雜度,評測鏈接

2020-02-05

arc103_d

令值域為 \(v\),本題中 \(v = {10}^9\)

每次操作,你必須讓 \(x\) 坐標或 \(y\) 坐標增加或減少一個定值 \(d\)

令一個點 \((x, y)\) 的奇偶性為 \((x + y) \bmod 2\),可以發現能夠操作到的點的奇偶性都相同,所以先把無解判掉。

好像沒有什么特別的構造方法。我們先考慮二進制拆分。

但是搞了半天之后,發現二進制拆分好像只能做到 \(2 (\lfloor \log_2 v \rfloor + 1)\) 次操作。

然后我們驚奇地發現,\(2 (\lfloor \log_3 v \rfloor + 2)\) 好像恰好就是 \(40\) 啊。

所以我們考慮把坐標表示成三進制數,注意這里三進制的系數,應該是 \(0, 1, -1\) 三種。

那么我們令 \(m = 40\)\(d_1 \sim d_m\) 分別為 \(1, 1, 3, 3, 9, 9, 27, 27, 81, 81, \ldots\)
也就是對於每一個 \(0 \le i \le 19\)\(3^i\)\(d\) 中出現兩次。
(如果所有點的奇偶性為 \(1\),則去掉一個 \(3^{19}\)

接下來構造解,每一位使用恰好兩個 \(3^i\)

我們從低位到高位考慮,假設考慮到了第 \(k\) 位。記 \(x_k, y_k\) 分別表示 \(x, y\) 坐標第 \(k\) 位的值。

  1. \(x_k = 0, y_k = 0\)
    RL 操作,也就是讓 \(x\) 減去 \(1\) 再加上 \(1\),也就是不變。
  2. \(x_k \ne 0, y_k \ne 0\)
    R/L 操作中的一個,讓 \(x_k\) 變成 \(0\)
    U/D 操作中的一個,讓 \(y_k\) 變成 \(0\)
  3. \(x_k \ne 0, y_k = 0\)
    如果 \(x_k = 1\),做 LL 操作,讓 \(x_k\) 變成 \(3\)
    如果 \(x_k = -1\),做 RR 操作,讓 \(x_k\) 變成 \(-3\)
    無論是哪種操作都需要進/借位,最后 \(x_k\) 還是變成了 \(0\)
  4. \(x_k = 0, y_k \ne 0\)
    類似上一種情況。

特別地,如果考慮到了第 \(k = 19\) 位:

  1. 點的奇偶性為 \(0\):只會出現上述情況中的 1, 2 兩種。
  2. 點的奇偶性為 \(1\):只剩一個 \(3^{19}\) 了,\(x_k, y_k\) 也必然只有一個非 \(0\),做 R/L/U/D 操作中的一個即可。

因為 \(\lfloor \log_3 v \rfloor = 18\),所以可以證明在執行上述操作時,只會影響到第 \(0 \sim 19\) 位。

時間復雜度為 \(\mathcal O (N \log_3 v)\)評測鏈接


看了題解后發現我是睿智,可以用二進制的,而且只需要 \(32\) 次。

2020-02-06

cf553E

\(f(i, k)\) 為第 \(i\) 個點在 \(k\) 時刻,最佳策略下到達終點的代價期望值;類似定義 \(g(j, k)\) 表示第 \(j\) 條邊的代價期望值。

\(f\)\(g\) 互相轉移,以 \(k\) 為階段可以發現都是從大往小轉移。最終答案就是 \(f(1, 0)\)

固定 \(f(i, \ast)\)\(g(j, \ast)\),轉移形式是一個卷積,用分治 FFT 優化即可。

一開始的邊界條件要先跑一下最短路。

時間復雜度為 \(\mathcal O (n^3 + m t \log^2 t)\)評測鏈接

agc022_e

這道題挺神的,我嘗試用比較好理解的方式解釋一下:

我們考慮判斷一個已知的串是否合法。

首先一個顯然的事實:假設我們把串的某一位從 0 變成了 1,那么一定是變優了,反之一定是變劣了。

也就是說,單獨修改某一位的優劣性,是可以簡單判斷的。

接下來我們列舉一些操作的情況:
11a => 1
10a => a
01a => a
00a => 0
1ab => (a|b)
0ab => (a&b)

又有一結論:如果 \(S\) 形如 11...,那么一定合法,這是因為,只要把后面的部分縮起來,再縮 11a 得到 1 即可。

我們再考慮串形如 00... 時,因為遲早要對 00 進行操作,我們不妨直接考慮對 00 進行操作時:
假設串形如 00ab...,那么操作 00a 得到 0b...,操作 0ab 得到 0(a&b)...
顯然前者不劣於后者,所以直接操作前者即可。也就是說 00a... == 0...

考慮串形如 01... 時,同樣地,直接考慮對 01 進行操作時:
假設串形如 01ab...,那么操作 01a 得到 ab...,操作 1ab 得到 0(a|b)...
a=0b=1 時,前者不劣於后者。當 a=1b=0 時,兩種操作分別得到 10...01...

到底是 10... 優還是 01... 優呢?這里我們先不作解答。

考慮串形如 10... 時:
假設串形如 10ab...,那么操作 10a 得到 ab...,操作 0ab 得到 1(a&b)...
a=1 時,前者不劣於后者。當 a=0b=0 時,后者不劣於前者。當 a=0b=1 時,兩種操作分別得到 01...10...

又回到了比較 10...01... 的問題上。

我們考慮 10xy...01xy...

  1. 如果 x=0,則前者可以得到 0y...10...;而后者可以得到 0y...
    此時,前者不劣於后者。
  2. 如果 x=1,則前者可以得到 1y...;而后者可以得到 1y...01...
    如果 y=1,前者不劣於后者。
    如果 y=0,兩者都能得到 10...,而后者還可以得到 01...
    但是不能無限地往后接 10 循環,最終一定會變成 10a01a,但是它們的結果確實是相同的,沒有孰優孰劣。

所以結論是 10...01... 更優。

一個例子是:1000101001,前者是合法的串,而后者不是。

那么我們構造如下轉移圖:

其中綠邊表示 \(0\) 的轉移,紅邊表示 \(1\) 的轉移,橙邊表示 \(0, 1\) 都是這個轉移。

然后在這個自動機上轉移即可。最終答案為 111 上的方案數之和。

時間復雜度為 \(\mathcal O (|S|)\)評測鏈接

arc101_e

直接 DP 的話大概是 \(\mathcal O (N^3)\) 的,使用容斥原理:

要計算的就是 \(\displaystyle \sum_{S \subseteq E} {(-1)}^{|S|} f(S)\),其中 \(f(S)\) 表示強制不能覆蓋到 \(S\) 中的邊的方案數。

也就是把 \(S\) 內的邊都刪掉,原樹被分割成了若干連通塊,每個連通塊內部連線的方案數。

顯然一個大小為 \(n\) 的連通塊,任意連線的方案數為 \(1 \cdot 3 \cdot 5 \cdot \cdots \cdot (n - 1)\)(如果 \(n\) 是偶數,\(n\) 是奇數的話顯然沒有方案)。

那么設狀態 \(dp(i, j)\) 表示考慮 \(i\) 的子樹,割掉若干條邊,\(i\) 所在的連通塊大小為 \(j\),的貢獻總和(不算 \(i\) 所在連通塊的貢獻)。

轉移也是顯然的。

時間復雜度為 \(\mathcal O (N^2)\)評測鏈接

arc101_f

首先,每個機器人只會從它旁邊的兩個出口離開。

對於旁邊只有一個出口的機器人,直接不管它就行,不會影響答案。

對於旁邊有兩個出口的機器人,我們只需要保存它到兩個出口之間的距離。

上述處理都可以通過雙指針來完成。

現在問題就變成了,給定 \(k\)\(0 \le k \le N\))個機器人,第 \(i\) 機器人到它左邊和右邊的出口的距離分別為 \(x_i\)\(y_i\)

我們把每個機器人畫在坐標系中,第 \(i\) 個機器人的位置就是 \((x_i, y_i)\)

可以發現,相當於我們操控兩條直線,初始時這兩條直線的位置分別為 \(x = 0\)\(y = 0\),也就是在坐標軸上。

我們可以把豎線往右移動,把橫線往上移動。如果線碰到了一個點,這個點就被這條線吃掉,然后消失。

問點被線吃掉的,不同的方案數。

我們考慮這兩條線的交點形成的軌跡,可以發現,在軌跡上方的點是被豎線吃掉的,在軌跡下方的點是被橫線吃掉的。

那么我們考慮統計這條軌跡穿過這些點的方案數。限制是軌跡必須是增函數。

我們把坐標離散化一下,用樹狀數組優化 DP 就可以做了。

具體地說,我們把所有點按照橫坐標遞增排序。然后考慮某條豎線上的點如何轉移。

\(dp(i, j)\) 表示,考慮了橫坐標 \(\le i\) 的點了,並且軌跡下的點的縱坐標最大值為 \(j\) 的方案數。

\(dp(i, j)\) 可以轉移到 \(dp(i + 1, j)\)\(dp(i + 1, y)\)(存在點 \((i + 1, y)\) 滿足 \(y > j\))。

用樹狀數組維護。

時間復雜度為 \(\mathcal O (M + N \log N)\)評測鏈接

2020-02-07

arc103_f

假設滿足條件的樹為 \(T\),我們考慮 \(T\) 的一些性質。

首先 \(T\) 只有一個重心,因為如果有兩個,那么它們兩個的 \(D\) 值就應該相同,與題意矛盾。

顯然重心就是 \(D\) 值最小的那個點。

\(T\) 以重心為根,容易發現,任何一個非根節點的 \(D\) 值都大於它的雙親節點的 \(D\) 值。

我們選取 \(D\) 最大的那個點 \(u\),顯然它必須是葉子。

我們可以計算出它的雙親節點的 \(D\) 值應該恰好為 \(D_u - N + 2 \cdot \mathrm{siz}\),其中 \(\mathrm{siz}\)\(u\) 的子樹大小(此時為 \(1\))。

那么就可以唯一確定它的雙親節點是哪一個。

然后把該點“刪去”,並讓它的雙親節點的 \(\mathrm{siz}\) 加上 \(1\)

重復 \(n - 1\) 次這個過程。就可以確定出 \(T\) 的形態。

也就是說,滿足條件的 \(T\) 其實是唯一的。

這時我們再 DFS 檢查一下是否確實滿足條件即可。

時間復雜度為 \(\mathcal O (N \log N)\)評測鏈接

agc020_d

首先我們可以得出:最短的連續段長度等於 \(\displaystyle \left\lceil \frac{\max\{A, B\}}{\min\{A, B\} + 1} \right\rceil\! = \!\left\lfloor \frac{A + B}{\min\{A, B\} + 1} \right\rfloor\),令這個值為 \(K\)

觀察 \(A \ge B\) 的情況(留作練習,請讀者自行完成)(大霧)

可以發現,一組 \(A, B\) 的答案,就是當 \(A = (B + 1) K\) 時的答案(形如 \([B \cdot (K \cdot \texttt{"A"} + \texttt{"B"}) + K \cdot \texttt{"A"}]\)),
去掉靠后的恰好 \((B + 1) K - A\)\(\texttt{"A"}\) 得到的,令這個值為 \(\mathrm{del}\)

但是並不一定是去掉最后 \(\mathrm{del}\)\(\texttt{"A"}\),考慮 \(A = 8, B = 6\) 的情況:\(\texttt{"AABAABAABABABB"}\)
它就是 \(A = 14, B = 6\) 的情況:\(\texttt{"AABAABAABAABAABAABAA"}\) 去掉 \(6\)\(\texttt{"A"}\) 得到的,但是不是最后 \(6\) 個。

這是因為如果去掉了最后 \(6\) 個,就會有 \(3\)\(\texttt{"B"}\) 形成連續段,與「連續段長度不大於 \(2\)」沖突。

也就是說,貪心地去掉盡可能靠后的 \(\mathrm{del}\)\(\texttt{"A"}\),但是不形成 \((K + 1) \cdot \texttt{"B"}\) 的連續段。

討論一下就可以得到結果了。

對於 \(A < B\) 的情況類似,是 \(B = (A + 1) K\) 時的答案(形如 \([A \cdot (K \cdot \texttt{"B"} + \texttt{"A"}) + K \cdot \texttt{"B"}]\)),
去掉盡可能靠前(不是靠后)的若干個 \(\texttt{"B"}\) 得到的,類似做就行了。

時間復雜度為 \(\mathcal O (Q (D - C + 1))\)評測鏈接

2020-02-08

arc099_f

考慮記前綴和信息 \((\Lambda_i, \delta_i)\) 表示依次吃掉 \(1 \sim i\) 的所有字符后,得到的序列和指針 \(P\) 的位置。

那么兩信息的合並:\((\Lambda_1, \delta_1) \circ (\Lambda_2, \delta_2) = (\Lambda_1 + \Lambda_2 \gg \delta_1, \delta_1 + \delta_2)\)

我們記 \(h_i\)\(\displaystyle \sum_{p} \Lambda_i[p] \beta^p\)

則有 \((h_1, \delta_1) \circ (h_2, \delta_2) = (h_1 + h_2 \beta^{\delta_1}, \delta_1 + \delta_2)\)

考慮 \(g = h_n\),一個區間 \([i, j]\) 的信息等於 \(g\) 當且僅當 \(h_{j - 1} + g \beta^{\delta_{j - 1}} = h_i\)

那么我們從后往前枚舉 \(j\),維護一個 \(h_i\) 的桶,以統計答案。

\(h\) 哈希一下就可以存進桶里了,為了防止沖突需要使用雙哈希。

時間復雜度為 \(\mathcal O (N \cdot \mathcal T (\mathrm{hash}))\)評測鏈接

agc031_d

根據題意,我們可以得到 \(a_i = a_{i - 1} {(a_{i - 2})}^{-1}\)。其中 \(q p\) 表示置換的復合,滿足 \({(q p)}_i = q_{p_i}\)

\(a_0\)\(a_{11}\) 列出,可得:

\[\begin{array}{rrcl} (a_0) =& & q^{-1} p &\\ a_1 =& & p & \\ a_2 =& & q & \\ a_3 =& & q p^{-1} & \\ a_4 =& & q p^{-1} q^{-1} & \\ a_5 =& & q p^{-1} q^{-1} p q^{-1} & \\ a_6 =& (q p^{-1} q^{-1} p) & q^{-1} p & (p^{-1} q p q^{-1}) \\ a_7 =& (q p^{-1} q^{-1} p) & p & (p^{-1} q p q^{-1}) \\ a_8 =& (q p^{-1} q^{-1} p) & q & (p^{-1} q p q^{-1}) \\ a_9 =& (q p^{-1} q^{-1} p) & q p^{-1} & (p^{-1} q p q^{-1}) \\ a_{10} =& (q p^{-1} q^{-1} p) & q p^{-1} q^{-1} & (p^{-1} q p q^{-1}) \\ a_{11} =& (q p^{-1} q^{-1} p) & q p^{-1} q^{-1} p q^{-1} & (p^{-1} q p q^{-1}) \\ \end{array} \]

所以是有個長度為 \(6\) 的循環節。

\(z = q p^{-1} q^{-1} p\),則 \(a_K\) 可以表示為 \(z^{K \div 6} a_{K \bmod 6} {(z^{-1})}^{K \div 6}\)

時間復雜度為 \(\mathcal O (N \log K)\)評測鏈接

cf587D

容易發現這是一個 2-SAT 的形式。

要求刪除 \(t\) 盡量小的邊,那就先二分答案。

不過還是要考慮建圖的問題。

如果直接建圖的話,會發現每個點周圍的邊都會互相影響,也就是刪掉其中一條就不能刪另一條。

直接建邊的話要建 \(\mathcal O ({deg}^2)\) 條。

其實限制就是,一個點周圍的邊,最多刪一條。

那么我們再在 2-SAT 模型中新建若干個變量,\(s_i\) 表示前 \(i\) 條邊是否被刪去。

如果 \(s_i = 1\),那么就有 \(s_{i + 1} = 1\)\(a_{i + 1} = 0\)

如果 \(a_i = 1\),那么就有 \(s_i = 1\)

大概是個鏈前綴和的形式。

這樣子邊數就是線性的了。

時間復雜度為 \(\mathcal O (m \log m + m \log t)\)評測鏈接

cf674F

這里我就抄 CMXRYNP 的題解了。

從能夠得到的信息考慮。

最多有 \(\min\{p, n - 1\}\) 只熊要去睡覺,我們先讓 \(p\)\(n - 1\)\(\min\)

那么對於每只熊,我們可以知道它有沒有去睡覺,如果有可以知道它在第幾晚去睡覺的。

所以最多的情況數就是:

\[\sum_{k = 0}^{p} \binom{n}{k} i^k \]

也就是枚舉 \(k\) 只熊去睡覺了,然后 \(i\) 是天數。

這是桶數量的一個上界。因為再怎么改變策略最后也只有這么多種情況。

我們可以證明這個上界是可以被達到的。

把所有情況編號,對於第 \(x\) 種情況,令沒有去睡覺的熊不碰第 \(x\) 個桶,在第 \(a\) 天去睡覺的熊恰好在第 \(a\) 晚去喝第 \(x\) 個桶里的飲料。

這樣子如果第 \(x\) 桶里是酒,就恰好會生成這種情況,所以每種答案對每種情況是一個滿射,然而它們數量相同,所以是一一對應的。

所以只要求出這個多項式的系數就行,系數就是組合數模 \(2^{32}\),記一下 \(2\) 的次數,遞推一下就行。

時間復雜度為 \(\mathcal O (p \log \mathrm{MOD} + q \cdot p)\),其中 \(\log \mathrm{MOD}\) 為快速冪復雜度,評測鏈接

agc024_e

相當於是,從一個空串開始,每次往里面加入一個 \([1, K]\) 之間的字符,加入 \(N\) 次,使得字符串的字典序遞增。

先把每個串的末尾加上字符 \(0\)

可以發現,加入字符(假設我們在字符 \(y\) 前插入字符 \(x\))后字典序遞增,當且僅當:

  1. \(x > y\)
  2. \(x = y\),且 \(x > y\) 之后第一個不同的字符。

我們插入的時候,只關心字符串是否相同,不關心插入的位置。

所以假設是第二種情況,我們可以把插入的位置往后挪到那個不同的字符之前。

這樣子既不會統計到重復的串,又避免了難考慮的 2 情況,一舉兩得。

現在只需要考慮 1 情況,也就是每次插入的字符必須插入在一個比它小的字符之前。

我們可以把插入的形式抽象化為一棵樹:
根節點為 \(0\),權值也為 \(0\)
假設第 \(i\) 次在字符 \(y\) 之前插入了字符 \(x\),如果 \(y\) 是在第 \(j\) 次插入的,就令 \(i\)\(j\) 的兒子,權值為 \(x\)

可以發現這樣的樹,只需要滿足:節點編號為 \(0 \sim N\),節點權值為 \(0 \sim K\),且孩子節點的編號和權值,要分別大於當前節點的編號和權值。

考慮令 \(dp(i, j)\) 表示,一棵 \(i\) 個點的樹,節點編號為 \(0 \sim i - 1\),根節點權值為 \(j\),且滿足上述條件的方案數。

有轉移:\(\displaystyle dp(i, j) = \sum_{k = 1}^{i - 1} \binom{i - 2}{k - 1} dp(i - k, j) \sum_{j < x \le K} dp(k, x)\)

組合意義是:考慮編號為 \(1\) 的節點,它一定是根節點的孩子,且形成一個子問題,枚舉 \(1\) 節點的子樹大小,假設為 \(k\),將除了 \(0, 1\) 之外的 \(i - 2\) 個編號分配給除了 \(1\) 之外的 \(k - 1\)\(1\) 的子樹中的點,這里貢獻一個 \(\displaystyle \binom{i - 2}{k - 1}\);除了 \(1\) 子樹外的大小為 \(i - k\),這里貢獻一個 \(dp(i - k, j)\)\(1\) 節點的權值為 \((j, K]\) 中的整數,這里貢獻一個 \(\displaystyle \sum_{j < x \le K} dp(k, x)\)

后一個和式用后綴和優化,狀態轉移的總時間復雜度為 \(\mathcal O (N^2 K)\)

答案就為 \(dp(N + 1, 0)\)

時間復雜度為 \(\mathcal O (N^2 K)\)評測鏈接

2020-02-10

cf538G

通過坐標變化,把曼哈頓距離轉成切比雪夫距離。

也就是說四個方向 RLUD,原本是橫縱坐標選取其中一個加減 \(1\),現在變成可以分別確定橫縱坐標是加還是減。

所以這就變成了一個一維的問題,好考慮一些。具體地說,只要把 \((x, y)\) 變成 \((x + y, x - y)\) 就行。

接下來考慮一維問題,只要分別解決了兩個一維問題,顯然就可以拼成答案。

假設操作序列為 \(c\),則 \(c\) 是個 \(\pm 1\) 串。通過 \(x_i \gets (x_i + t_i) / 2\),可以把 \(c\) 轉成 \(01\) 串。

則我們考慮 \(c\)\(01\) 串的情況,令 \(s\)\(c\) 的前綴和。
則有 \(s_i \le s_{i + 1} \le s_i + 1\)

考慮每個時刻,還有 \(x_i = \lfloor t_i / l \rfloor s_l + s_{t_i \bmod l}\)

\(s = s_l\),如果確定了 \(s\),就可以直接判斷是否合法了。
具體的說,根據獲得的 \(n\) 個時刻的信息,可以確定出 \(s_i\) 中一些位置的值了,然后根據 \(s_i \le s_{i + 1} \le s_i + 1\) 進一步判斷。

但是現在不知道 \(s\),如何求出 \(s\) 呢。

我們把所有信息:\(c_i s + s_{p_i} = x_i\) 按照 \(p_i\) 從小到大排序。
\(c_i = \lfloor t_i / l \rfloor\)\(p_i = t_i \bmod l\)

不過在排序之前,要在這些信息里加上兩條:\(0 s + s_0 = 0\)\((-1) s + s_l = 0\)

然后考慮相鄰的兩條信息,就可以列出不等式確定 \(s\) 的范圍。

最后求得的 \(s\) 是一個區間,任取里面任何一個值都可以。

具體證明我也不太懂,反正 AC 了(

其它實現細節見代碼。

時間復雜度為 \(\mathcal O (n \log n + l)\)評測鏈接

agc035_d

可以發現 \(A_1\)\(A_N\) 沒啥用,不用考慮它們,然后最后加到答案里去就行。

那也就是說,現在有 \(N - 2\) 個數排成一行,你每次可以刪掉其中一個,它就會加到左右兩邊去。

特別的,如果它在最左邊,它就會被加到一個變量 \(L\) 上,如果它在最右邊,它就會被加到一個變量 \(R\) 上。

最后要讓 \(L + R\) 最小。

這時可以考慮倒着做。假設最后一個刪掉的元素,是 \(i\)

那么 \(i\) 左邊的數,一部分扔到 \(L\) 里了,一部分扔到 \(i\) 上了,\(i\) 右邊的數,一部分扔到 \(R\) 里了,一部分扔到 \(i\) 上了。

然后刪除 \(i\) 本身,就有那些扔到 \(i\) 上的數,以及 \(i\) 本身,都會被加到 \(L\)\(R\) 上。

那么我們假設,\(i\) 左邊的數刪除后,加到 \(i\) 上,總共加了 \(x\)。那么這 \(x\) 最后產生的貢獻就是 \(2x\),因為加到了 \(L\)\(R\) 上。

右邊同理,只不過換了個方向,也是兩倍貢獻。

既然倒着考慮了,那就要想到區間 DP。我們觀察 \(i\) 左邊的區間,這段區間中的數,加到左邊會對總答案貢獻 \(1\) 倍,但是加到右邊會貢獻 \(2\) 倍。

於是定義如下狀態:\(dp(l, r, cl, cr)\) 表示考慮區間 \([l, r]\) 中的數,把它們刪除后,會對總答案貢獻 \(cl \cdot L + cr \cdot R\),要使這個貢獻最小。

則最終答案為 \(dp(2, N - 1, 1, 1) + A_1 + A_N\)

有轉移:

\[dp(l, r, cl, cr) = \min_{i = l}^{r} [ dp(l, i-1, cl, cl + cr) + dp(i + 1, r, cl + cr, cr) + (cl + cr) A_i ] \]

特別地,如果 \(l > r\),則 DP 值為 \(0\)

容易發現,DP 狀態數的上界是 \(\mathcal O (N^2 2^N)\),因為區間只有 \(\mathcal O (N^2)\) 對,而后面的系數的增長可以看作一個 \(N\) 層的二叉樹的形態。

經過一些精細計算,其實 DP 狀態數和轉移數只有 \(\mathcal O (2^N)\),這里就略去不證了。

時間復雜度為 \(\mathcal O (2^N)\)評測鏈接

agc033_e

不失一般性,我們假設 \(S[1] = \texttt{R}\),如果不成立則把兩種顏色互換即可,不影響答案。

因為一開始就必須走紅弧,所以環上不能出現相鄰的藍弧。也就是說,環上的每一段藍弧的長度均為 \(1\)

如果 \(S\) 全部都是 \(\texttt{R}\),則不需要其他限制了,答案就為 \(2F_{N - 1} + F_N\)\(F\) 為斐波那契數列,\(F_0 = 0, F_1 = 1\))。

否則至少有一個 \(\texttt{B}\),初始的一段 \(\texttt{R}\) 后必然會跟着一個 \(\texttt{B}\),所以那時必須要走到藍弧旁邊。

由此可得,一定不會出現一段連續的紅弧,滿足長度為偶數。也就是說每段連續的紅弧的長度一定是奇數。

如果出現了長度為偶數的紅弧,則如果一開始的位置在這段弧上,且到兩端的藍弧的距離的奇偶性和 \(S\) 中第一段 \(\texttt{R}\) 的長度不一樣,就一定不可能在 \(\texttt{R}\) 結束時到達藍弧旁邊(注意到因為長度是偶數,才有到兩端的藍弧的距離的奇偶性相同。如果長度為奇數,能保證恰好有一端距離的奇偶性與 \(S\) 中第一段 \(\texttt{R}\) 的長度相同)。

進一步地,假設 \(S\) 中第一段 \(\texttt{R}\) 的長度為 \(l_1\),則每段紅弧的長度,不能超過 \((l_1 + [l_1 \bmod 2 = 0])\)(因為恰好有一端是可行的,到那一端的距離不能太大)。

接着,考慮 \(S\) 之后的每一段連續的 \(\texttt{R}\)

如果這一段 \(\texttt{R}\) 之后沒有接着一個 \(\texttt{B}\),也就是說它在 \(S\) 的末尾,那么對它就沒有限制。

否則,考慮它的長度,假設為 \(l_i\)。因為這一段 \(\texttt{R}\) 的上一個字符必然也是 \(\texttt{B}\)(不是第一段了),所以一開始時必然是在某一段紅弧的端點上。如果 \(l_i\) 為奇數的話,就要走到對面的端點上才行,否則一直在相鄰的紅弧上反復橫跳就行。也就是說,如果 \(l_i\) 為奇數的話,這一段紅弧的長度最長不能超過 \(l_i\);如果是偶數的話不產生影響。當然,因為起點是任選的,所以每一段紅弧也都具有了這個性質。

總的來說,就是說每一段紅弧的長度被限制了,最小是 \(1\),最大不妨令它為 \(k\),且要是奇數。然后要計算形成一個環的方案數。

我們把一段紅弧,和它在逆時針方向的第一個藍弧,算作一段,這樣每一段的長度就必須是 \(2 \sim (k + 1)\) 之間的偶數,所以 \(N\) 也必須是偶數。

環上的情況不好考慮,必須要轉化成序列。

我們考慮第一個弧所在的那一段,假設那一段的長度為 \(x\),則有 \(x\) 種方法旋轉,使得第一個弧仍然在那一段中。

那么也就是說,對於所有的權值是 \(\le k\) 的正偶數,總和為 \(N\) 的序列 \(A\),每一個序列會為答案貢獻 \(A_1\) 種方案。

也就是枚舉 \(A_1\),然后計算總和為 \(N - A_1\) 的序列的數量,乘以 \(A_1\) 后貢獻給答案。

總和為 \(i\) 的序列的個數很好算,只要枚舉最后一個元素是多少就行了,有轉移:\(\displaystyle f(i) = \sum_{j = 2}^{k} [j \bmod 2 = 0] f(i - j)\)

用前綴和優化一下就完事了。

時間復雜度為 \(\mathcal O (N + M)\)評測鏈接

2020-02-11

cf634F

如果固定上下邊界,那么中間的點,按照縱坐標排序,就可以統計答案了。所以這樣子是 \(\mathcal O (r^2 n)\) 的。

那我們固定上邊界,往下推下邊界呢?那就是變成每次插入一個點,會影響它周圍的 \(k\) 個點對答案的貢獻。

但是動態插入,比較不好維護。那我們就從下往上推下邊界,現在就變成刪除,可以用鏈表快速定位和找周圍的 \(k\) 個點。

時間復雜度為 \(\mathcal O (n \log n + r^2 + r n k)\)評測鏈接

2020-02-12

cf666E

因為不會 SAM,所以用 SA。

我們考慮 Height 數組的 Kruskal 重構樹,其實是和后綴樹等價的。

那一次詢問就是查詢一棵子樹中,出現次數最多的顏色,以及它出現的次數。

線段樹合並即可(好像是我第一次寫線段樹合並)。

時間復雜度為 \(\mathcal O ((l + q) \log m)\),其中 \(\displaystyle l = |s| + \sum |t_i|\)評測鏈接

cf611H

可以發現只要是無序對 \((a_i, b_i)\) 相同的邊,都可以只看做一類,這樣就只有最多 \(6 (6 + 1) / 2 = 21\) 類邊。

同時位數相同的點,也可以看作一類,這樣只有最多 \(6\) 類點。

\(m = \lfloor \log_{10} n \rfloor + 1\),點的類數就為 \(m\),邊的類數就為 \(m (m + 1) / 2\)

可以發現不同種類的點,不管怎么樣也還是要連接起來的。

那么先特判一下 \(m = 1\) 的情況,然后可以證明一個結論:存在一種方案,滿足:

  • 每一類點都選出一個“關鍵點”,例如第 \(i\) 類點的關鍵點編號可以為 \({10}^{i - 1}\)
  • 只考慮這 \(m\) 個關鍵點,它們形成的導出子圖,是一棵樹,也就是一個 \(m\) 個點 \(m - 1\) 條邊的樹連接了所有“關鍵點”。
  • 其它所有點只與“關鍵點”連接,也就是不存在“非關鍵點”之間的連邊。

詳細證明這里從略。

那么,我們考慮枚舉連接所有“關鍵點”的樹形態,比如使用 Prüfer 序列枚舉,這部分的時間復雜度為 \(\mathcal O(m^{m - 2})\)

枚舉完成后,對應種類的邊就用掉了對應條,這里記得先扣掉。

然后考慮每一條邊 \((u, v)\),可以是 \(u\) 類“非關鍵點”連到 \(v\) 類“關鍵點”上,也可以是 \(v\) 類“非關鍵點”連到 \(u\) 類“關鍵點”上。

總之,一條邊 \((u, v)\) 將會把 \(u\) 類或者 \(v\) 類的“非關鍵點”的剩余個數減去 \(1\)

這樣一來就可以轉化為一個帶權(重數)二分圖完美匹配的模型。

具體地說,左側有 \(m (m + 1) / 2\) 個點,表示每一類邊,右側有 \(m\) 個點,表示每一類點。

左側的每個點,帶的權值(重數)為剩余的對應類型的邊的數量。

右側的每個點,帶的權值(重數)為剩余的對應類型的點的數量。

不難發現這兩個數量之和相等。左側的每個點,假設它對應的邊的類型為 \((u, v)\),它向右側的 \(u, v\) 類點對應的點分別連邊。

使用網絡流可以解決帶重數的二分圖匹配問題,這里寫個 Dinic 水過去。

Dinic 跑完之后也可以直接構造方案了。

時間復雜度為 \(\mathcal O (m^{m + 4})\)評測鏈接

2020-02-13

cf613E

對於 \(|w| \le 2\) 的情況,我們進行特判,這是為了之后寫起來分類討論可以簡潔一些。

觀察一下最終的行走方式可能會變成啥樣:

很多情況下,會變成這個樣子。

注意到可以分成三段,左邊一個 U 形,中間一個只會向右走的形狀,右邊又一個 U 形。

啊,為啥說中間是只會向右走?因為我們是這么欽點的,當然也可能是從右邊出發往左走,這時只要把 \(w\) 反轉,再求一次就行。

我們可以處理出,從一個地方分段,會不會產生向左的,長度為某個值的 U 形。

這可以通過預處理 LCP 做到。

同理可以處理出,從一個地方分段,會不會產生向右的,長度為某個值的 U 形。

處理上述兩個數組,它們就能夠作為第一部分和第三部分。

我們把第二部分接在第一部分后,記 \(f(i, j, k)\) 表示,當前第二部分走到了 \((i, j)\),並且匹配了 \(w\) 的前 \(k\) 個字符,並且不是從同一列走來的方案數。

類似地,記 \(g(i, j, k)\) 為必須從同一列走來的方案數。則 \(f, g\) 之間可以互相轉移,這部分可以 \(\mathcal O (n |w|)\) 處理。

然后考慮在 DP 到 \((i, j, k)\) 時,接上第三部分即可,可以直接判斷接不接得上。

當然還有一些其他情況沒有討論的,比如三個部分中的某一部分並不存在,甚至是兩個部分不存在之類的,仔細討論一下即可。

注意要不重不漏,特別注意 \(w\) 反轉后不要統計重復了。

時間復雜度為 \(\mathcal O (n |w|)\)評測鏈接

cf566E

如果兩個集合的交為 \(2\),則交出來的這兩個點,之間一定有連邊。

這樣可以確定樹中所有非葉子節點之間的連邊情況。

先特判非葉子節點數為 \(0, 1, 2\) 的情況。

\(0\) 的話就是 \(n = 2\);為 \(1\) 的話就是菊花,每個集合大小都是 \(n\);為 \(2\) 的話就是有恰好兩個集合大小是 \(n\)

現在非葉子節點數至少是 \(3\)。那么我們需要確定每個葉子掛在了哪個非葉子上。

注意到我們在給非葉子節點連邊的時候,就可以處理出每個非葉子節點,與其相連的非葉子節點的集合,也就是距離 \(\le 1\) 的集合。

那么我們依次考慮每個葉子,它對應的集合就是所有集合中,包含這個葉子的,大小最小的那個。

在這個集合中,去掉所有葉子節點,就得到了與它相連的非葉子節點的鄰接非葉子節點集合。

再枚舉每個非葉子節點,就可以判斷具體是和哪一個非葉子節點相連的了。

時間復雜度為 \(\displaystyle \mathcal O \!\left( \frac{n^3}{w} \right)\),其中 \(w\) 為字長,評測鏈接

cf573E

考慮一個貪心策略:一開始選空集,然后每次選一個不在集合中的數加入集合,具體選哪個數呢?選擇讓新的答案最大的數即可。

然后集合大小從 \(0\) 逐漸增大到了 \(n\),得到了 \(n + 1\) 個答案,我們選取其中最大的一個輸出。

我們發現這樣做成功 TLE 了(悲),但是並沒有 WA,說明貪心是對的(確信)。

具體證明請下載 徐翊軒的題解 查看。

那么我們只需要快速維護這個貪心,具體地說,每個位置有一個權值 \(b_i\) 和一個固定的值 \(a_i\),需要支持四種操作:

  1. 前綴 \(b_i\) 加相同值。
  2. 后綴 \(b_i\)\(a_i\)
  3. 查詢 \(b_i\) 的全局最大值。
  4. 刪除一個位置。

一般線段樹沒法做,我們考慮分塊。(其實這是一種經典分塊類型)

\(\sqrt{n}\) 個元素分一塊,那對於每一塊就要實現:

  1. 整體加。
  2. 整體加 \(a_i\)
  3. 查詢整體最大值。
  4. 重構。

可以發現大概是類似斜率優化那套式子,維護上凸殼即可。

注意到 \(a_i\) 始終不變,而要求的斜率不斷遞減,可以用單調隊列維護,重構的時候也不用重新排序了。

本題還有 \(\mathcal O (n \log n)\) 的做法,在題解中同樣可以看到。不過因為要手寫平衡樹,我比較懶就不寫了。

時間復雜度為 \(\mathcal O (n \sqrt{n})\)評測鏈接

2020-02-18

cf627F

設初始時 \(0\)\(s\),目標時在 \(t\)

注意到操作的本質是 \(0\) 的移動,同時操作具有可逆性。

因此,我們先不考慮次數最少的要求,先讓 \(0\)\(s\) 以最短距離移動到 \(t\)

如果此時已經滿足目標狀態了,說明不需要加入新的邊,此時 \(0\) 經過的距離即為最少步數。

否則,接下來我們只能加入一條新的邊,然后讓 \(0\)\(t\) 出發,走到包含這條新邊的環上距離 \(t\) 最近的點 \(p\),繞若干次完整的圈之后,回到 \(t\)

觀察這樣操作對權值的變化可以得出,\(t\)\(p\) 的路徑上的所有點的權值都不會改變,同時每繞圈一次,環上除了 \(p\) 之外的點上的權值變化形成一個循環,而繞若干圈則為一個輪換

因此,權值要改變的點加上 \(p\) 應該在樹上形成一條路徑。

由此我們能夠確定連邊 \((u,v)\),可以 \(t\) 為根,找到所有權值需要改變的點,\(p\) 即為這些點中深度最小的點的父節點,而路徑 \((u,v)\) 則由 \(p\) 和這些點構成。

如果深度最小的點的父節點不唯一,或者 \(p\) 和這些點無法構成一條路徑,或者這些點的權值不是目標權值的一個輪換,則說明無解。

最后來考慮最小化操作次數。

對於一條加邊 \((u,v)\),繞圈的方向有兩種 \(u \to v\)\(v \to u\),分別計算取 \(\min\) 即可。

假設從 \(u \to v\),由這個輪換對循環的次數 \(c\) 可以得到最小次數為 \(2\cdot \operatorname{dist}(t, p) + c \cdot (\operatorname{dist}(u, v) + 1)\)

但注意這個最小次數是在先將 \(0\)\(s\) 移到 \(t\) 的前提下,因此如果有重復的路徑需要減掉。

准確地說,如果是 \(u \to v\),那就是將 \(0\) 直接從 \(s\) 經過樹邊移動到 \(u\),然后經過新加的邊移動到 \(v\),然后在這個環上再繞 \((c - 1)\) 圈回到 \(v\),最后經過樹邊移動到 \(t\)。此時的答案也就是 \(\operatorname{dist}(s, u) + (c - 1) \cdot (\operatorname{dist}(u, v) + 1) + \operatorname{dist}(v, t) + 1\)

如果是 \(v \to u\),只要把 \(u, v\) 互換,並重新計算循環的次數 \(c\) 即可。

時間復雜度為 \(\mathcal O (n)\)評測鏈接

2020-02-19

arc093_f

淘汰賽的比賽結構是一個完全二叉樹,假設玩家 \(1\) 被安排在了某個位置,則他要最終獲得勝利的話,需要打敗 \(N\) 個對手。

\(N\) 個對手分別來自大小為 \(2^0, 2^1, 2^2, \ldots , 2^{N - 1}\) 的子樹中。

也就是說,它們是那些對應的子樹中的最小值。

要讓 \(1\) 取得勝利,這些值中不能有那 \(M\)\(A_i\) 之一。

這相當於,把除了 \(1\) 以外的 \(2^N - 1\) 個數染上 \(N\) 種顏色,第 \(i\) 種顏色恰好要染 \(2^{i - 1}\) 個數。

而且對於每種顏色,最小的,染上這種顏色的數,不能是任何一個 \(A_i\)

然后我們考慮容斥原理,假設一個集合中的 \(A_i\) 都必須是某個顏色的最小值。

可以發現讓 \(A_i\) 從大到小 DP 會比較合適。記一個狀態表示比當前值大的 \(A_i\) 被強制選取了哪些顏色的最小值,也就是說哪些顏色已經被用掉了。

轉移的時候,該 \(A_i\) 可以不強制選,直接轉移;或者強制選成某個還未被選擇的顏色 \(k\) 的最小值,DP 值乘上 \(\displaystyle \binom{s - 1}{2^{k - 1} - 1}\),其中 \(s\) 表示后面還沒有被選中的數的個數,\(s\) 可以直接由當前 \(A_i\) 和選取的顏色狀態計算得出。

最后答案就是容斥得到的染色方案數,乘以 \(\displaystyle 2^N \prod_{i = 1}^N (2^{i - 1})!\),這是因為每個子樹內可以任意排,然后 \(1\) 每次可以從左子樹或右子樹上來。

時間復雜度為 \(\mathcal O (M N 2^N)\)評測鏈接

2020-02-20

cf506E

不考慮題目中的“在原串中插入”,我們直接統計最終的長度為 \(N = |s| + n\) 的回文串的個數。

接下來的問題是:給定一個回文串,如何判斷 \(s\) 是否作為一個子序列出現。

當然可以直接子序列自動機,但是這樣子的性質不夠好。考慮從 \(s\) 的兩側進行匹配。

假設當前回文串為 \(t\),我們使用 \(t\) 兩側的字符對 \(s\) 兩側的字符進行匹配:
假設 \(t\) 兩端的字符為 \(c\),如果 \(s\) 左端的字符也為 \(c\),就刪去這個字符,右邊同理。

\(s = \mathtt{abaac}, t = \mathtt{{\color{red}b}{\color{magenta}a}{\color{blue}c}{\color{Tan}b}{\color{ForestGreen}a}{\color{Tan}b}{\color{blue}c}{\color{magenta}a}{\color{red}b}}\) 為例:

  • \(\mathtt{{\color{red}b}}\) 去匹配 \(s\) 的兩端,\(s\) 變為 \(\mathtt{abaac}\)
  • \(\mathtt{{\color{magenta}a}}\) 去匹配 \(s\) 的兩端,\(s\) 變為 \(\mathtt{{\color{magenta}a}baac}\)
  • \(\mathtt{{\color{blue}c}}\) 去匹配 \(s\) 的兩端,\(s\) 變為 \(\mathtt{{\color{magenta}a}baa{\color{blue}c}}\)
  • \(\mathtt{{\color{Tan}b}}\) 去匹配 \(s\) 的兩端,\(s\) 變為 \(\mathtt{{\color{magenta}a}{\color{Tan}b}aa{\color{blue}c}}\)
  • \(\mathtt{{\color{ForestGreen}a}}\) 去匹配 \(s\) 的兩端,\(s\) 變為 \(\mathtt{{\color{magenta}a}{\color{Tan}b}{\color{ForestGreen}a}a{\color{blue}c}}\)
    注意,這里只能匹配其中一個字符,因為 \(\boldsymbol{t}\) 中只剩下一個 \(\mathtt{{\color{ForestGreen}a}}\) 了!

如果 \(s\) 少一個 \(\mathtt{a}\) 或者 \(t\) 多一個 \(\mathtt{{\color{ForestGreen}a}}\),就能全部匹配。

如果按照這種方式全部匹配完了,就是合法的串。

由此我們可以構造一個 DP:\(dp(x, i, j)\) 表示確定了 \(t\) 的左右兩端各 \(x\) 個字符后,恰好匹配到 \(s\) 中的子串 \(s[i : j]\)\(t\) 的方案數。
並且一個特殊的狀態 \(dp(x, \mathrm{done})\) 表示匹配完了。

則答案就為 \(\displaystyle dp \!\left( \left\lceil \frac{N}{2} \right\rceil\!, \mathrm{done} \right)\)

對應的轉移圖如下:

但是因為 \(N\) 太大,沒法直接這樣做,直接做的復雜度是 \(\mathcal O ({|s|}^2 N)\) 的。

觀察到這個轉移圖,顯然就是用來矩陣快速冪的,但是還是不行,復雜度是 \(\mathcal O ({|s|}^6 \log N)\) 的。

所以還是觀察一下性質,比如我們可以發現,紅色點就代表 \(s\) 的兩端不同的情況,綠色點表示相同的情況。

那么要到達終點,如果經過了 \(n_1\) 個紅色點,就必須要經過 \(\displaystyle \left\lceil \frac{|s| - n_1}{2} \right\rceil\) 個綠色點。

然后發現終點前的點一定是綠色點,所以最多經過 \(|s| - 1\) 個紅色點,也就是說經過的紅色點的數量在 \(0\)\(|s| - 1\) 內。

我們單獨把一條從起點到終點的鏈拿出來,可以發現,經過的紅點和綠點的順序實際上沒有影響,也就是說把紅點提前答案不變:

這個性質十分重要,因為本質不同的鏈的個數只有 \(\mathcal O (|s|)\) 個,所以只要求出每種鏈的個數就行了,同樣可以使用類似的 DP 得到。

這樣的話,考慮在每一條鏈上做矩陣快速冪,得到的答案乘以鏈的條數再相加就是總答案,復雜度是 \(\mathcal O ({|s|}^4 \log N)\) 的。

我們可以更進一步優化,考慮這樣的自動機(字符串長度為 \(|s| = 5\) 時,也就是和剛才舉的例子相同):

其中 \(g_0 \sim g_{|s| - 1}\) 分別表示經過的紅點個數分別為對應值的鏈的個數。

可以發現恰好滿足每一條本質不同的鏈都能夠被表示出,而且不重復不遺漏。

在這個自動機上做矩陣快速冪就行了,因為加了一個空的起點,所以要多走一步。

但是這樣直接求的話,對於 \(N\) 是奇數的情況會多算,就是前文提到的那種情況(最中心的字符只能匹配一個)。

我們這樣考慮,先求出在 \(\displaystyle \left\lfloor \frac{N}{2} \right\rfloor\) 步內就能到達終點的方案數,乘以 \(26\)(還能再走一步)。

然后再加上在 \(\displaystyle \left\lfloor \frac{N}{2} \right\rfloor\) 步時恰好到達一開始的自動機中的 \(s\) 被刪到長度為 \(1\) 時的節點的方案數。

計算第二種情況時,也要重新計算一下 \(g_0 \sim g_{|s| - 1}\),最終就能求得總答案了。

時間復雜度為 \(\mathcal O ({|s|}^3 \log N)\)評測鏈接

arc096_e

考慮容斥,枚舉有 \(a\) 個只出現了一次,\(b\) 個一次都沒出現。

則給答案貢獻 \(\displaystyle {(-1)}^{a + b} \binom{n}{a} \binom{n - a}{b} 2^{2^{n - a - b}} \sum_{x = 0}^{a} {a \brace x} {(2^{n - a - b})}^x\)

如果令 \(c = a + b\),變換為 \(\displaystyle {(-1)}^c \binom{n}{c} 2^{2^{n - c}} \sum_{x = 0}^{c} {(2^{n - c})}^x \sum_{a = x}^{c} {a \brace x} \binom{c}{a}\)

考慮這個恆等式:\(\displaystyle \sum_{i = x}^{n} {i \brace x} \binom{n}{i} = {n + 1 \brace x + 1}\)

所以答案為 \(\displaystyle \sum_{c = 0}^{n} {(-1)}^c \binom{n}{c} 2^{2^{n - c}} \sum_{x = 0}^{c} {(2^{n - c})}^x {c + 1 \brace x + 1}\)

時間復雜度為 \(\mathcal O (N^2 + N \log M)\)評測鏈接

2020-02-21

cf575E

可以證明如下結論:

在平面直角坐標系中,給定若干個不全都共線的點。
要作一個半徑盡量大的圓,使得該圓包含所有給定點,並經過至少三個給定點。
構造給定點構成的凸包,並要求凸包上不存在共線的三個頂點。由於這些點不全都共線,所以一定存在這樣的凸包。
則有結論:要求的圓一定經過凸包上三個相鄰頂點。

具體證明請下載 任清宇的題解 查看。

所以只要求出給出的點集的凸包后,枚舉凸包上相鄰三點計算並更新答案即可。

具體地說,由於每個人能夠到達的點的凸包是一個點,或一個 \(3 \sim 6\) 邊形,只要求出每個人對應的凸包的頂點,這可以通過簡單的討論求出,再合並求一次大凸包即可。

時間復雜度為 \(\mathcal O (n \log n)\)評測鏈接

cf607E

為了方便考慮,把坐標系平移到以 \((p, q)\) 為原點處。

那么以原點為圓心作圓,只要找到圓內有 \(m' < m\) 個交點的最大半徑即可。

那么答案就等於圓內交點到原點的距離之和,加上 \(m - m'\) 倍的半徑。

二分答案后考慮如何 check 是否有 \(< m\) 個交點。

把每個與圓有交的直線拿出來,就變成圓上的一條弦,對應了圓上極角序的一個區間。

就變成了對相交但不包含的區間對計數的問題,是二維偏序問題。

這部分時間復雜度為 \(\mathcal O (n \log n (\log v - \log \varepsilon))\)

確定了對應半徑后,再使用類似方法在 \(\mathcal O (n \log n + m)\) 的時間內統計交點到原點的距離即可。

時間復雜度為 \(\mathcal O (n \log n (\log v - \log \varepsilon) + m)\)評測鏈接

2020-02-22

arc092_f

對於一條邊 \(u \to v\),將它反向后變成 \(v \to u\),會對原圖的強連通分量個數造成影響,當且僅當:

  • 忽略這條邊后,\(u\) 能直接或間接到達 \(v\)
  • 忽略這條邊后,\(v\) 能直接或間接到達 \(u\)

這兩個條件僅恰好滿足一個。證明不難,請自行腦補。

其中,忽略 \(u \to v\) 后,詢問 \(v\) 是否能夠到達 \(u\),和不忽略其實也沒啥區別,所以這部分可以直接做,\(\mathcal O (NM)\) 的復雜度就可以接受了,當然你也可以用 bitset 做 \(\mathcal O (M + NM / w)\)

然后考慮忽略 \(u \to v\) 后,詢問 \(u\) 是否能夠到達 \(v\),也就是只要存在第一條邊不走 \(u \to v\) 的簡單路徑就行。

我們考慮對於所有的起點相同,也就是 \(u\) 相同的 \(u \to v\) 計算這個東西,那么只要一次的時間復雜度為 \(\mathcal O (M)\) 就可以接受了。

首先把 \(u\) 的出邊排成一排,假設終點分別為 \(v_1, v_2, \ldots , v_k\)

那么先按照正序,也就是 \(v_1, v_2, \ldots , v_k\) 的順序進行 DFS,並記錄每個點是從哪個點到達的(就是從哪個 \(v_i\) 出發),記做 \(p(v_i)\)

然后按照逆序,也就是 \(v_k, v_{k - 1}, \ldots , v_1\) 的順序進行 DFS,並記錄每個點是從哪個點到達的,記做 \(q(v_i)\)

如果一個 \(v_i\) 可以從其它 \(v_j\)\(j \ne i\))出發到達它,當且僅當 \(p(v_i) \ne q(v_i)\),只要判斷這個條件即可。

時間復雜度為 \(\mathcal O (NM)\)評測鏈接

2020-02-23

agc023_f

第一步,必須把根節點刪掉。

然后可以發現,如果刪掉一個節點之后,它的孩子中有 \(0\),那就可以立刻把孩子也刪掉,這樣答案不會變得更劣。

那我們把 \(0\) 和它的父親並成一個連通塊,表示這個連通塊可以一次性取完,最后整棵樹就變成了一些不相交連通塊。

然后會發現,如果此時我們把每個連通塊看成一個節點,還是一棵樹的結構,但是這時每個連通塊內就有若干個 \(0\)\(1\) 混合了。

現在僅考慮新樹的兩個節點 \(u, v\),忽略其它的影響:

假設 \(x\)\(0, 1\) 的個數分別為 \(x_0, x_1\),則如果 \(u\) 排在 \(v\) 前面,就會增加 \(u_1 v_0\) 對逆序對,反之增加 \(v_1 u_0\) 對。

如果 \(u_1 v_0 < v_1 u_0\),則 \(u\) 排在 \(v\) 前面肯定更優。

變換一下式子,變成 \(\displaystyle \frac{u_1}{u_0} < \frac{v_1}{v_0}\),也就是連通塊中 \(1\)\(0\) 個數的比值。

考慮當前這個比值最小的連通塊,假設為 \(a\),則可以發現當 \(a\) 的父親被取到的時候,下一步一定會把 \(a\) 取了。

這是因為無論連通塊怎么合並,這個比值都不會變得比原來更小,也就不會小於 \(a\) 的比值。

所以,拿一個支持插入刪除,取出最小值的數據結構(比如 set),就可以維護了。

具體地說就是每次取出這個比值最小的連通塊,把它的它的父親合並。

時間復雜度為 \(\mathcal O (n \log n)\)評測鏈接

2020-02-25

agc038_f

\(P\) 分解成不相交循環的乘積后,考慮其中一個循環 \((a_1, a_2, \ldots , a_k)\)

不失一般性,可以把這個循環看作 \((1, 2, \ldots , k)\)

那么對於 \(A_1\),有兩種情況:\(A_1 = 1\)\(A_1 = P_1 = 2\)

如果 \(A_1 = 1\),則考慮 \(A_k\) 有兩種情況:\(A_k = k\)\(A_k = P_k = 1\),但是因為 \(A_1 = 1\),所以只能有 \(A_k = k\)
以此類推,可以得到:對於這個循環中的所有元素 \(i\),均有 \(A_i = i\)

如果 \(A_1 = 2\),則考慮 \(A_2\) 有兩種情況:\(A_2 = 2\)\(A_2 = P_2 = 3\),但是因為 \(A_1 = 2\),所以只能有 \(A_2 = 3\)
以此類推,可以得到:對於這個循環中的所有元素 \(i\),均有 \(A_i = P_i\)

換句話說,對於每個循環,要么這個循環被完全保留,要么這個循環被完全拆解成一個個自環。

上述結論對 \(Q\)\(B\) 當然也適用。

我們稱選擇一個循環,指這個循環被完全保留,稱不選一個循環,指這個循環被拆解成了一個個自環。

接着,考慮一個 \(P\) 中的循環 \(a\) 和一個 \(Q\) 中的循環 \(b\),假設它們共有一個元素 \(i\)。分若干類討論:

  1. \(P_i = Q_i = i\):無論如何,這個位置上均有 \(A_i = B_i\)
  2. \(P_i = i, Q_i \ne i\):如果選擇\(b\),則這個位置上有 \(A_i \ne B_i\),否則不選 \(b\),則這個位置上有 \(A_i = B_i\)
  3. \(P_i \ne i, Q_i = i\):如果選擇\(a\),則這個位置上有 \(A_i \ne B_i\),否則不選 \(a\),則這個位置上有 \(A_i = B_i\)
  4. \(P_i \ne i, Q_i \ne i, P_i \ne Q_i\):如果不選 \(a\)不選 \(b\),則這個位置上有 \(A_i = B_i\),否則這個位置上有 \(A_i \ne B_i\)
  5. \(P_i \ne i, Q_i \ne i, P_i = Q_i\):如果 \(a, b\) 同時選擇或同時不選,則這個位置上有 \(A_i = B_i\),否則這個位置上有 \(A_i \ne B_i\)

最終需要最大化 \(A_i \ne B_i\) 的下標 \(i\) 的數量,也就是最小化 \(A_i = B_i\) 的下標 \(i\) 的數量。

如果在上述 \(5\) 種情況中,一旦發生了 \(A_i = B_i\),就賦有 \(1\)代價,那么就是要最小化總代價。

可以發現類似於一個文理分科模型,可以建立一個網絡流模型,求最小割得到答案。

但是因為有些條件不符合,沒法直接套用。

不過,如果把 \(Q\) 中的循環割掉與源點和匯點之間的邊的意義交換,就可以套用了。

而且可以發現,這樣建出來的圖是一個二分圖,因為 \(P\) 中的循環只和源點連邊,\(Q\) 中的循環只和匯點連邊,\(P, Q\) 之間也只會互相連邊。(如果 \(P\) 中的循環對應的節點,割掉與源點相連的邊的意義是不選它,而 \(Q\) 中的循環對應的節點的意義恰好相反的話)

所以最終是在單位容量的二分圖上求最小割,使用 Dinic 算法可以做到 \(\mathcal O (|E| \sqrt{|V|})\) 的復雜度。

時間復雜度為 \(\mathcal O (N \sqrt{N})\)評測鏈接

agc023_d

如果 \(X_1 < S < X_N\),考慮第 \(1\) 棟樓和第 \(N\) 棟樓。

如果 \(P_1 \ge P_N\),即第 \(1\) 棟樓中的人數大於等於第 \(N\) 棟樓中的人數,則班車一定會先去第 \(1\) 棟樓。證明:

  • 如果 \(N = 2\),顯然成立。
  • 如果 \(N \ge 3\)\(X_{N - 1} < S\),顯然除了第 \(N\) 棟樓的員工,都希望前往負方向,所以一定會前往負方向。
  • 如果 \(N \ge 3\)\(S < X_{N - 1}\),如果在到達第 \(1\) 棟樓之前沒有到達第 \(N - 1\) 棟樓,則結論成立,否則轉化為前兩種情況。

所以說不管怎么樣都會先前往第 \(1\) 棟樓,然后就可以一路向右徑直跑到第 \(N\) 棟樓。

這就意味着,第 \(N\) 棟樓中內的員工的回家時間,一定等於第 \(1\) 棟樓的回家時間,加上 \(X_N - X_1\)

也就是說,第 \(N\) 棟樓中的員工,其實是和第 \(1\) 棟樓中的員工站在同一條線上的。第 \(1\) 棟樓的員工想投什么票,他們也一定會跟着投。所以說這第 \(N\) 棟樓的員工其實和第 \(1\) 棟樓的員工沒什么區別,暫時(在第 \(1\) 棟樓的員工回家之前)讓他們搬家到第 \(1\) 棟樓也對運行路徑沒有影響。

所以說,如果讓 \(P_1 \gets P_1 + P_N\),然后刪去第 \(N\) 棟樓,計算這種情況下的到達第 \(1\) 棟樓的時間,加上 \(X_N - X_1\) 就是答案。

如果 \(P_1 < P_N\),那么以上結論的方向反過來即可。

這樣遞歸下去,直到不滿足 \(X_1 < S < X_N\) 為止,那樣的話就可以直接計算答案了。

時間復雜度 \(\mathcal O (N)\)評測鏈接

2020-02-26

agc036_d

考慮差分約束模型,圖中不存在負環等價於存在一組合法的差分約束的解。

考慮每個節點作為一個變量,第 \(i\) 個節點對應的變量為 \(x_i\)

因為初始的邊不能刪去,所以一定有 \(x_i \ge x_{i + 1}\)

考慮令 \(q_i = x_i - x_{i + 1}\),那么就會有 \(q_i \ge 0\)

假設保留了一條邊權為 \(-1\)\(i \to j\) 的邊,也就是說 \(i < j\) 的話:
就會有 \(x_i - 1 \ge x_j\),即 \(x_i - x_j \ge 1\),也就是說 \(q_i + q_{i + 1} + \cdots + q_{j - 1} \ge 1\)

假設保留了一條邊權為 \(1\)\(i \to j\) 的邊,也就是說 \(i > j\) 的話:
就會有 \(x_i + 1 \ge x_j\),即 \(x_j - x_i \le 1\),也就是說 \(q_j + q_{j + 1} + \cdots + q_{i - 1} \le 1\)

反過來想,如果確定了所有的 \(q_i\),那么每一條邊就應該盡可能地保留下來,這樣代價最小。

對於邊權為 \(-1\) 的邊,是區間和 \(\ge 1\) 才能保留,也就是說如果區間和 \(= 0\) 就必須刪除。

對於邊權為 \(1\) 的邊,是區間和 \(\le 1\) 才能保留,也就是說如果區間和 \(\ge 2\) 就必須刪除。

也就是說,對於一種 \(q\) 的取值方案,\(q_i = 0\) 的每個連續段,都對應着一系列的邊權為 \(-1\) 的邊的刪除。

而區間和 \(\ge 2\) 的區間也對應着邊權為 \(1\) 的邊的刪除。

顯然可以發現,如果出現了 \(q_i \ge 2\),不如把它變成 \(1\),這樣一定會變得更優(邊 \(i \to (i + 1)\) 不用被刪除了)。

所以只需要考慮 \(q\) 的取值為 \(\{0, 1\}\) 的情況。

然后可以發現,每個 \(0\) 的連續段就對應着一部分區間的刪除,所以考慮如下 DP:

\(dp(i, j)\) 表示考慮到了 \(q_i\),最后一個 \(1\) 取在了 \(q_i\),倒數第二個 \(1\) 取在了 \(q_j\) 處的情況下,可以確定的代價的最小值。

\(dp(i, j)\) 可以從 \(dp(j, k)\) 轉移而來,利用二維前綴和可以快速求出轉移系數。

時間復雜度為 \(\mathcal O (N^3)\)評測鏈接

2020-02-27

agc026_e

\(a_i\) 表示第 \(i\)\(\mathtt{a}\) 的位置,\(b_i\) 表示第 \(i\)\(\mathtt{b}\) 的位置。

考慮如何比較兩個字符串的字典序,可以發現當某個前綴相同時應該比較后綴,所以考慮從后往前 DP:

\(dp(i)\) 表示只考慮所有的 \(a_{i \sim N}\)\(b_{i \sim N}\),也就是第 \(i\) 對以及之后的 \(\mathtt{a}, \mathtt{b}\) 的情況下的字典序最大的串。

注意不是\(i\)\(\mathtt{a}, \mathtt{b}\) 以及它們之后的所有字符都一定選擇,而是一對一對的選擇的。

那么答案就為 \(dp(1)\)。而 \(dp(i)\) 可以從兩個方向轉移,也就是 \(a_i\)\(b_i\) 保留或者刪掉。

如果刪掉,就直接從 \(dp(i + 1)\) 轉移而來。

否則考慮如果保留第 \(i\)\(\mathtt{a}, \mathtt{b}\) 的話會怎么樣,根據先后順序分成兩類討論:

  1. \(a_i < b_i\):也就是形如 \(\cdots \mathtt{{\color{red}a}{\color{blue}a}{\color{green}b}{\color{blue}a}{\color{blue}a}{\color{green}b}{\color{red}b}} \cdots\) 的情況。
    紅色的字符就是第 \(i\)\(\mathtt{a}, \mathtt{b}\)綠色的字符表示第 \(i\) 對之前的字符,藍色的字符表示第 \(i\) 對之后的字符。
    注意綠色的字符只可能是 \(\mathtt{b}\),而藍色的字符只可能是 \(\mathtt{a}\)。因為綠色的字符不會被保留,之后忽略它們。
    既然已經確定了必須選取 \(a_i, b_i\),因為要讓字典序盡量大,所以 \(a_i\)\(b_i\) 之間所有的 \(\mathtt{a}\) 都應該被刪掉。
    也就是說,\(dp(i)\) 就應該等於 \(\mathtt{ab} + dp(k)\),其中 \(k\) 為完全在 \(b_i\) 之后的第一對 \(a_k, b_k\) 的編號。
  2. \(a_i > b_i\):也就是形如 \(\cdots \mathtt{{\color{red}b}{\color{blue}b}{\color{green}a}{\color{blue}b}{\color{blue}b}{\color{green}a}{\color{red}a}} \cdots\) 的情況。
    紅色的字符就是第 \(i\)\(\mathtt{a}, \mathtt{b}\)綠色的字符表示第 \(i\) 對之前的字符,藍色的字符表示第 \(i\) 對之后的字符。
    注意綠色的字符只可能是 \(\mathtt{a}\),而藍色的字符只可能是 \(\mathtt{b}\)。因為綠色的字符不會被保留,之后忽略它們。
    既然已經確定了必須選取 \(a_i, b_i\),因為要讓字典序盡量大,所以 \(a_i\)\(b_i\) 之間所有的 \(\mathtt{b}\) 都應該被保留。
    而確定要保留這些 \(\mathtt{b}\),又會導致往后包含了更多的 \(\mathtt{b}\),同理被包含的 \(\mathtt{b}\) 也應該被保留,連鎖反應會一直進行下去,直到某一次不包含了更多的 \(\mathtt{b}\) 為止。舉個例子:
    考慮 \(\mathtt{{\color{blue}b}b{\color{blue}a}babbbabaaaabbabaaaabb}\)
    選取 \(\mathtt{{\color{red}b}{\color{blue}b}{\color{red}a}b{\color{blue}a}bbbabaaaabbabaaaabb}\)
    選取 \(\mathtt{{\color{red}{bba}}{\color{blue}b}{\color{red}a}bbb{\color{blue}a}baaaabbabaaaabb}\)
    選取 \(\mathtt{{\color{red}{bbaba}}{\color{blue}{bbb}}{\color{red}a}b{\color{blue}{aaa}}abbabaaaabb}\)
    選取 \(\mathtt{{\color{red}{bbababbba}}{\color{blue}b}{\color{red}{aaa}}{\color{blue}a}bbabaaaabb}\)
    選取 \(\mathtt{{\color{red}{bbababbbabaaaa}}bbabaaaabb}\)
    在這種情況下,\(dp(i) = \mathtt{bbababbbabaaaa} + dp(k)\),其中 \(k\) 為后面部分的第一對 \(a_k, b_k\) 的編號。

所以只要求出以上兩類的結果就行,第 1 類可以預處理,第 2 類的開頭的字符串,可以直接掃一遍判斷。

時間復雜度為 \(\mathcal O (N^2)\)評測鏈接

cf679E

注意到在可能的值域(約為 \({10}^{14}\))內,\(42\) 的次冪並不多,嘗試從這個角度考慮。

操作 3 比較棘手,解決的辦法是用線段樹維護當前值到下一個 \(42\) 的次冪的差值。

做操作時讓這個差值做區間減法,在線段樹遞歸的時候,如果差值會變成負數,就需要再遞歸進子區間進行修改,但是如果這個區間被打上了區間覆蓋標記,就直接修改這個標記就行。

執行完后,如果存在差值為 \(0\) 的位置,就再執行一次。

這個做法的復雜度,使用勢能函數可以分析得出為 \(\mathcal O (q \log n \log_{42} v)\)

具體地說,令當前線段樹的勢能函數等於每個值相同的連續段,比此連續段的值大的,在值域內的 \(42\) 的次冪的個數的總和,乘以 \(\log n\)

則操作 2 和操作 3 的攤還代價都為 \(\mathcal O (\log n \log_{42} v)\)

時間復雜度為 \(\mathcal O ((n + q) \log n \log_{42} v)\),其中 \(v\) 為值域,約為 \({10}^9 q\)評測鏈接

2020-02-28

agc039_e

\(n = 2 N\),枚舉第 \(n\) 個點和哪個點連了,假設為 \(k\),即:

就分成了 \(1 \sim (k - 1)\)\((k + 1) \sim (n - 1)\) 兩段。

直接考慮如果是區間 \([i, j]\),且這區間中的一點 \(k\) 與區間外的一點連線了,即:

如果 \(i < j\),那么被 \(k\) 分割的左右兩邊必然要通過至少一條線與 \((? \leftrightarrow k)\) 連接起來

但是又不能交叉,如果交叉就形成環了,所以取最上方的一條線 \((x \leftrightarrow y)\)

所謂最上方,形式化地說就是 \(x\) 最靠近 \(i\)\(y\) 最靠近 \(j\)

那么,\(x, y\) 在兩邊必然就會有各自的“管轄范圍”。
(你可以理解成,從 \((? \leftrightarrow k)\)\((x \leftrightarrow y)\) 的交點出發向 \(x\)\(y\) 方向走,能遍歷到的區域,它和其它區域不相交)

假設這個范圍分別為 \([i, p]\)\([q, j]\)

那么如果我們枚舉 \(i, j, k, x, y, p, q\)(滿足 \(i \le x \le p < k < q \le y \le j\)):

就可以轉化成三個子問題 \([i, p](x)\)\([p + 1, q - 1](k)\)\([q, j](y)\)

可以在 \(\mathcal O (n^7)\) 的復雜度內解決此問題,因為常數大約是 \(1 / 7! = 1 / 5040\),所以其實是可以過的。


不過可以繼續優化,可以發現 \([i, p]\)\([q, j]\) 是和 \(k\) 獨立的,也就是如果 \([i, j]\) 固定,\(k\) 的位置不影響 \(p, q\) 的選擇。

那么我們考慮先枚舉 \(p, q\),得到 \([i, p] \circ [q, j]\) 這個子問題,再在子問題里枚舉 \(x, y\)

則處理所有 \([i, q] \circ [q, j]\) 就可以做到 \(\mathcal O (n^6)\) 的復雜度(枚舉 \(6\) 個變量)。

外層的 \([i, j](k)\) 就可以只枚舉 \(p, q\) 進行轉移,這部分復雜度為 \(\mathcal O (n^5)\)

總時間復雜度為 \(\mathcal O (n^6)\),同樣帶了一個 \(1 / 6! = 1 / 720\) 的常數。


不過可以繼續優化,現在復雜度瓶頸是在 \([i, p] \circ [q, j]\) 這里,需要枚舉 \(x, y\) 才能轉移。

如果只枚舉一個 \(y\) 呢?

那就需要求 \([i, p]\) 區間中的,從 \(y > p\) 連進來一條邊的方案數,用記號 \([i, p]\{y\}\) 表示。

當然還有本來就要求的 \([q, j](y)\),這個是舊的東西了。

那么考慮計算 \([i, p]\{y\}\),這時就可以枚舉具體是和哪個 \(i \le x \le p\) 連邊,然后直接加上 \([i, p](x)\) 即可。

所以處理所有 \([i, p]\{y\}\) 的復雜度為 \(\mathcal O (n^4)\),而處理所有 \([i, p] \circ [q, j]\) 的復雜度降為 \(\mathcal O (n^5)\)

總時間復雜度為 \(\mathcal O (n^5)\),帶了一個 \(1 / 5! = 1 / 120\) 的常數,評測鏈接


免責聲明!

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



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