Change Log
- 2022.2.1. 計划優化整篇文章,修改 POI2006 部分題解(修改至 P3449)。
- 2022.2.3 ~ 2.5. 新增了大概 \(50\) 道綠 ~ 藍題。
- 2022.2.20. 新增 P3462(2007), P3514(2010), P3523(2010)。
1997
P6701 [POI1997] Genotype
首先容易區間 DP 求出 \(f_{l, r}\) 能夠表示由哪個字符得到,狀壓存儲。來個 DP \(g_i\) 表示 \(i\) 前綴至少需要多少個 \(\texttt S\) 得到,轉移有 \(g_i = \min\limits_{j = 0} ^ {i - 1} g_j + 1\) 且需滿足 \(\texttt S\in f_{j + 1, i}\)。\(f_{l, r}\) 的轉移枚舉中間點 \(p\) 以及 \(f_{l, p}\) 中的所有字符 \(c\)。可以預處理字符 \(c\) 與字符集合 \(S\) 合並能得到哪些字符,但是這樣時空復雜度均為 \(26\times 2 ^ {26}\),無法接受,拆成 \(\leq \texttt M\) 和 \(> \texttt M\) 兩半預處理即可。 時間復雜度 \(\mathcal{O}(kL ^ 3|\Sigma| + 26\times 2 ^ {13})\)。
1998
*P5939 [POI1998]折線
將坐標系順時針旋轉 \(45 ^\circ\) 后,使用 Dilworth 定理轉化成最長上升子序列(經典導彈攔截)。注意對於橫坐標相同的點,需要先考慮縱坐標大的那個。
1999
P5929 [POI1999]地圖
不難看出區域顏色誤差就是一些城市的人口與人口中位數的差的絕對值之和。我們有關鍵性質:被划分到同一顏色的所有城市一定連續。調整法容易證明。
根據上述性質,考慮一個最朴素的 DP:設 \(f_{i, k}\) 表示用 \(k\) 種顏色划分前 \(i\) 個城市,區域顏色誤差之和的最小值。顯然有 \(f_{i, k} = \min\limits_{j = 0} ^ {i - 1} f_{j , k - 1} + w(j + 1, i)\),其中 \(w(i, j)\) 表示城市 \(i\sim j\) 的區域顏色誤差。
根據上述轉移式轉移,並預處理人口數量的前綴和從而 \(\mathcal{O}(1)\) 計算 \(w(i, j)\),可以做到 \(\mathcal{O}(mn^2)\),足夠通過本題。
可不可以再給力一點啊?可以。
關於貢獻函數 \(w\),它有非常好的性質:它滿足 四邊形不等式。可以證明對於 \(x_1 < x_2 < x_3 < x_4\),有 \(w(x_1, x_4) + w(x_2, x_3) \geq w(x_1, x_3) + w(x_2, x_4)\)。感性理解即可,證明留給讀者。因此這個動態規划滿足決策單調性,可以使用 決策單調性分治 優化,時間復雜度 \(\mathcal{O}(mn\log n)\)。
可不可以再給力一點啊?可以。
我們猜測 \(f_{n, k}\) 是關於 \(k\) 的凸函數,使用 wqs 二分 和二分隊列在 \(\mathcal{O}(n\log n\log V)\) 時間內解決,其中 \(V\) 是二分值域。
誒,這好像就是 IOI2000 郵局。破案了,IOI 竟然出原題。
2001
P1463 [POI2001][HAOI2007]反素數
經典老題。題目相當於求 \(n\) 以內約數個數最多的數。
有兩個性質:若用到質數 \(p\) 但沒用到質數 \(q\) 且 \(q < p\),把 \(p\) 換成 \(q\) 不改變約數個數但減小了數字,更優;若 \(p\) 的指數大於 \(q\) 且 \(q < p\),交換 \(p, q\) 的指數不改變約數個數但減小了數字。根據這兩個性質,我們只需用到前 \(9\) 個質數,爆搜很快出結果。
2003
*P3424 [POI2005]SUM-Fibonacci Sums
好題!先求和,再調整。
由於題目給出的 \(x, y\) 是齊肯多夫表示法,所以簡單地對應位求和 \(z = x + y\) 后,\(z_i = 0/1/2\)。
考慮從高往低位調整,即依次保證長為 \(1\) 的前綴,長為 \(2\) 的前綴 …… 直到整個數都滿足齊肯多夫表示法,類似 數學歸納法。因為從低到高涉及進位,很麻煩。下稱滿足齊肯多夫表示法為 合法。
我們發現最棘手的是 \(z_i = 2\),別的都好辦。由於 \(0200 = 0111 = 1001\),考慮一次操作 \(op(i)\) 表示令 \(z_i\gets z_i - 2\),\(z_{i + 1}\gets z_{i + 1} + 1\),\(z_{i - 2}\gets z_{i - 2} + 1\)。此時可能導致低位 \(3\) 的出現,但是問題不大,因為我們只關心 \(i\) 及其高位。
我們的目標是 盡可能消掉 \(2\),自然不希望已經處理好的高位重新出現 \(2\)。由於 \(i + 1\) 及其高位合法,所以不會出現連續的兩個 \(1\)。因此,若 \(z_{i + 1} = 1\) 且 \(z_i \geq 2\),\(op(i)\) 會令 \(z_{i + 1}\) 變成 \(2\)。
不妨先執行進位操作,即 \(z_i \gets z_i - 1\),\(z_{i + 1}\gets z_{i + 1} - 1\),\(z_{i + 2}\gets z_{i + 2} + 1\)。由於 \(z_{i + 2}\) 一定等於 \(0\),所以進位后等於 \(1\)。同時,若 \(z_{i + 3} = 1\),那么繼續進位到 \(z_{i + 4}\)。稱從 \(i\) 開始不斷進位的過程為 \(\mathrm{flush}(i)\),其代碼如下:
void flush(int p) {while(z[p] && z[p + 1]) z[p + 2]++, z[p]--, z[p + 1]--, p += 2;}
注意,當 \(i + 1\) 及其高位均合法時,操作才不會出錯,即操作結束后 \(i + 1\) 及其高位仍合法。容易證明這一點。否則可能出現數碼 \(2\)。如當 \(z_i = z_{i + 1} = z_{i + 2} = 1\) 時,這樣的進位導致 \(z_{i + 2} = 2\),破壞了齊肯多夫表示法,但若 \(i + 1\) 及其高位合法,則不會出現 \(z_{i + 1} = z_{i + 2} = 1\) 的情況。
執行完 \(0\) 或 \(1\) 次進位操作后,\(z_{i + 1} = 0\),因此若 \(z_i \geq 2\),再執行 \(\mathrm{op}(i)\) 僅會將 \(z_{i + 1}\) 變為 \(1\),且由於 \(z_i\leq 3\),故現在所有 \(i\) 及其高位均有 \(z \leq 1\),但 \(i + 1\) 及其高位不一定合法,因為可能 \(z_{i + 1} = z_{i + 2} = 1\)。由於此時 \(i + 2\) 及其高位合法,所以先 \(\mathrm{flush}(i + 1)\),再 \(\mathrm{flush}(i)\) 即可保證對於得到的結果,\(i\) 及其高位合法。
啰里啰嗦這么一大堆,只是為了嚴謹證明以下做法的正確性:
- 從高到低考慮每一位 \(i\)。保證 \(i + 1\) 及其高位合法。
- 首先 \(\mathrm{flush}(i)\)。
- 若 \(z_i \geq 2\),則依次執行 \(\mathrm{op}(i)\),\(\mathrm{flush}(i + 1)\),\(\mathrm{flush}(i)\)。
- 此時 \(i\) 及其高位合法。
特殊情況:\(\mathrm{op}(2)\) 令 \(z_1\gets z_1 + 1\),\(z_2 \gets z_2 - 2\),\(z_3\gets z_3 + 1\)。\(\mathrm{op}(1)\) 令 \(z_1\gets z_1 - 2\),\(z_2\gets z_2 + 1\)。不難發現我們對高位的影響最多僅是令 \(z_{i + 1}\) 加 \(1\),和普通的 \(\mathrm{op}(i)\ (i > 2)\) 是一樣的,故特殊情況也一定合法。
時間復雜度分析:考慮 \(d = \sum z_i\),每次進位均會讓 \(d\) 減少 \(1\),而 op
不改變 \(d\),故 flush
的總復雜度均攤為 \(d\),即總時間復雜度線性。
P5948 [POI2003]Chocolate
簡單貪心。將 \(x, y\) 從大到小排序並考慮每條豎線,先切代價更大的那一維。從大到小排序調整法可證(對於相同維度,先切代價小再切代價大不優),貪心策略調整法可證(將先切代價小的一維,再切代價大的一維不優)。時間復雜度線性對數。
P8059 [POI2003] Monkeys
連通性相關刪邊題目考慮時光倒流,求出每個猴子第一次與 \(1\) 連通的時間。直接 dfs 打標記即可。時間復雜度線性。
2004
P5911 [POI2004]PRZ
狀壓枚舉子集,時間復雜度 \(\mathcal{O}(3 ^ n)\)。
2005
*P3419 [POI2005]SAM-Toy Cars
本題貪心的思想還算比較巧妙:如果地板滿了,我們會選擇下一次被玩的時刻最晚那個玩具 \(i\) 放回去。證明的話經典調整法,設放了 \(j\) 回去,那么下次玩 \(j\) 時還要把 \(j\) 拿回來,把 \(i\) 放回去,相較於直接把 \(i\) 放回去多用了一步,不優。
維護時刻最晚的玩具,priority_queue
足矣。因為壓入一個玩具時,其在堆里面對應的下一次被玩的時刻永遠也不會取到,新的下一次被玩的時刻顯然大於原來的,故不需要任意刪除元素。時間復雜度 \(\mathcal{O}(p\log p)\)。
P3420 [POI2005]SKA-Piggy Banks
顯然,基環樹個數即為答案。
*P3421 [POI2005]SKO-Knights
巧妙線性代數題。題目要求我們找到兩個向量 \(d, e\),使得它們的 整系數 線性組合得到的線性空間(簡稱整系數線性空間)等價於給出的所有向量的整系數線性空間。定義 \(\mathrm{span}(S)\) 表示向量集合 \(S\) 的整系數線性空間,即
如果我們能將三個向量 \(a, b, c\) 合並成與之等價的兩個向量 \(d, e\),就能夠解決本題。根據基礎的線性代數知識,不改變矩陣行空間的初等行變換有三種:
- 兌換:對應本題即可以任意交換 \(a, b, c\)。
- 倍乘變換:對應本題即向量可以乘以任意非 \(0\) 整數。
- 倍加變換:對應本題即向量可以加上任意整數倍其它向量。
當然,上述性質僅在 實系數 線性組合的前提下成立。當要求系數為 整數 時,
- 兌換顯然不改變矩陣行空間。
- 倍乘變換 可能改變 矩陣行空間,因為 整數乘法不可逆。如 \(\mathrm{span}((0, 1), (1, 0))\neq \mathrm{span}((0, 2), (1, 0))\),前者是任意整點,后者是任意縱坐標是偶數的整點。
- 倍加變換 不改變 矩陣行空間:對於任意 \(p = y(a + xb) + zb\in \mathrm{span}(a + xb, b)\),它本質上仍是 \(a, b\) 的整系數線性組合 \(ya + (xy + z)b\)。對於任意 \(p = ya + zb \in \mathrm{span}(a, b)\),我們也總可以將其表示為 \(a + xb\) 和 \(b\) 的整系數線性組合 \(y(a + xb) + (z - xy) b\)。
很好!如果整系數倍加變換不改變整系數意義下的矩陣行空間,就可以使用 輾轉相減法。具體地,考慮兩個向量 \(a, b\),我們能夠在 不改變其整系數線性空間 的前提下,將 \(b\) 的某一維變為 \(0\)。只需對 \(a, b\) 在這一維進行輾轉相減法即可。
考慮三個向量 \(a, b, c\),我們對 \(a, b\) 在 \(x\) 這一維進行輾轉相減,再對 \(a, c\) 在 \(x\) 這一維進行輾轉相減。此時 \(x_b, x_c\) 均為 \(0\),意味着 \(b, c\) 共線。因此,對 \(b, c\) 在 \(y\) 這一維進行輾轉相減,就可以使 \(y_b\gets \mathrm{gcd}(y_b, y_c)\),而 \(c\) 變成了 零向量,對 \(\mathrm{span}(a, b, c)\) 沒有任何貢獻,可以 直接舍去,即此時 \(\mathrm{span}(a, b, c) = \mathrm{span}(a, b)\)。綜上,我們在 \(\mathcal{O}(n\log V)\) 的時間內解決了問題,其中 \(V\) 是值域。
注意點:題目限制了坐標絕對值不超過 \(10 ^ 4\),因此輾轉相減法得到最終的 \(a\) 時,\(x_a\) 和 \(y_b\) 是原坐標的 \(\gcd\),顯然滿足坐標限制。但 \(y_a\) 不一定,因此要對 \(y_b\) 取模,也相當於做了一步輾轉相減(此時 \(x_b = 0\) 所以不需要改變 \(x_a\))。故最終得到的坐標絕對值不超過 \(10 ^ 2\),比題目限制優一個數量級。
從上述過程中,我們也可以發現一個有趣的性質:整系數 意義下,兩個向量可以在不改變其張成的前提下,使其中一個向量的 某一維變成 \(0\),而另一個向量的對應維變成原來兩個向量在這一維上的 \(\gcd\)。這也是解決本題的關鍵性質。
因此,推廣到任意維度 \(k\),給定 \(n\) 個 \(k\) 維向量,我們可以 \(nk ^ 2\log V\) 求出這組向量在整系數意義下的基。誒,等等?這不就是 線性基 么!
讓我們更加深入地鑽研一下題解區的做法。實際上兩者的核心思想是等價的,均為剛才提到的性質:將兩個向量的其中一個的某一維變成 \(0\),另一個的對應維變成 \(\gcd\)。不同點在於本文的線性代數做法是從 倍加變換 和 輾轉相除法 開始,推得 這一核心思想,即我們運用正確性有保證的方法,最終得到的結果是這樣一個性質。而題解區做法是首先令這一條件成立,再根據得到的線性方程組,使用 exgcd 和一些數學推導求解。這也體現了 exgcd 與輾轉相除的本質聯系。
不妨設對於向量 \(a, b\),我們要將 \(x_b\) 變為 \(0\)。此時 \(x_{a'}\) 已經確定,即 \(\gcd(x_a, x_b)\)。因此,對於方程 \(xx_a + yx_b = \gcd(x_a, x_b)\),容易用 擴展歐幾里得 算法求得一組解,則 \(y_{a'} = xy_a + yy_b\)。這是因為 \(a' = xa + yb\)。對於向量 \(b'\),有 \(x_{b'} = 0\),因此有線性方程組
注意該方程組的 \(x, y\) 與之前 exgcd 求得的 \(x, y\) 不同。同時我們需使 \(y_{b'}\) 絕對值最小,否則可能出現 \(y_{b'} = 2\),但 \((0, 1) \in \mathrm{span}(a, b)\) 的情況,即對於 \(\mathrm{span}(a, b)\) 中橫坐標為 \(0\) 的所有點,\((0, y_{b'})\) 不是與 \((0, 0)\) 相鄰的那一個,這樣與 \((0, 0)\) 相鄰的點無法表示。
根據第一個方程,得到 \(x, y\) 的關系式 \(y = \dfrac{-xx_a}{x_b}\)。帶入第二個方程,得到 \(xy_a - \dfrac{xx_ay_b}{x_b} = y_{b'}\),即
我們的目標很明確:找到 絕對值 最小的合法的 \(x\)。把 \(x\) 寫成 \(\dfrac {x_b}d\) 的形式(因為分母是 \(x_b\)),那么 \(y = -\dfrac{x_a} d\),因此 \(d\) 滿足
注意到若滿足前兩條限制,則第三條限制自動滿足,故忽略。為使 \(x\) 的絕對值最小,\(d\) 的絕對值應盡量大。到這一步,大家應該都能看出 \(d\) 應取 \(\gcd(x_a, x_b)\)。因此,\(y_{b'} = \dfrac{y_ax_b - x_ay_b}{\gcd(x_a, x_b)}\)。
綜上,我們將原向量 \(a, b\) 寫成了另兩個向量 \(a', b'\),其中 \(x_{a'} = \gcd(x_a, y_a)\),\(y_{a'}\) 用 exgcd 求解,\(x_{b'} = 0\),\(y_{b'} = \dfrac{y_ax_b - x_ay_b}{\gcd(x_a, x_b)}\)。對 \(a, c\) 做一遍類似的操作,再合並 \(b, c\)(即類似線性代數解法,令 \(y_b \gets \gcd(y_b, y_c)\),然后丟棄 \(c\))即可。時間復雜度也是線性對數。
另一種求解 \(y_{b'}\) 的思路(來源於 TheLostWeak 的博客):\(a', b'\) 可以整系數線性組合出 \(a, b\),否則顯然不滿足條件,因為 \(a, b\in \mathrm{span}(a, b)\)。
根據上述性質,考慮 \(a'\)。由於 \(x_{a'} = \gcd(x_a, x_b)\),所以為了使橫坐標等於 \(x_a\),需要為 \(a'\) 乘以 \(\dfrac{x_a}{\gcd(x_a, x_b)}\) 即 \(\dfrac{x_a}{x_{a'}}\) 的系數,得到 \(\left(x_a, \dfrac{x_ay_{a'}}{x_{a'}}\right)\)。由於我們可以通過向量 \(b' = (0, y_{b'})\) 得到 \((x_a, y_a)\),因此 \(y_{b'} \left |\ y_a - \dfrac{x_ay_{a'}}{x_{a'}}\right.\) 。同理,\(y_{b'} \left |\ y_b - \dfrac{x_by_{a'}}{x_{a'}}\right.\)。故
易證若 \(y_{b'}\) 小於上述 \(\gcd\),將導致存在 \(p\in \mathrm{span}(a', b')\),\(p\notin \mathrm{span}(a, b)\)。若 \(y_{b'}\) 大於上述 \(\gcd\),\(a', b'\) 無法整系數線性組合出 \(a, b\) 中的至少一個。
聯立后兩種方法描述 \(y_{b'}\) 的式子,稍作化簡后得到等式 \(y_ax_b - x_ay_b = \gcd(y_ax_{a'} - x_a y_{a'}, {y_bx_{a'} - x_by_{a'}})\)。這也許說明了某些性質,但筆者已經不想研究了 QAQ,感興趣的讀者可自行鑽研。
P3422 [POI2005]LOT-A Journey to Mars
POI 真的很喜歡出 單調隊列!一開始看錯題,以為可以來回走,以為是個神題,想了兩個小時 ……
首先破環成鏈,考慮從 \(i\) 開始順時針方向 \(i\to i + 1\to i + 2 \to \cdots \to i + n - 1 \to i + n\) 能不能走到,也就是要滿足 \(p_i \geq d_i\),\(p_i + p_{i + 1}\geq d_i + d_{i + 1}\) …… 前綴和 優化一下即對於每個 \(k\in [i, i + n - 1]\),都要有 \(p_k - p_{i - 1} \geq d_k - d_{i - 1}\),稍做變形得到 \(p_{i - 1} - d_{i - 1} \leq \min\limits_{i\leq k < i + n} p_{i - 1} - d_{i - 1}\),經典的滑動窗口。
對於逆時針方向,同理要有 \(d_{i - 1} - p_i \leq \min\limits_{i - n\leq k < i} d_{k - 1} - p_k\)(手動模擬一下容易得到),也是滑動窗口。時間復雜度線性。
P3423 [POI2005]BAN-Bank Notes
單調隊列優化多重背包板子題。由於要記錄轉移點,時空復雜度 \(\mathcal{O}(nk)\)。
2006 (2021.12.11-12.14)
做一發出生年的 POI(霧)。
P3434 [POI2006]KRA-The Disks
對 \(r_i\) 求前綴 \(\min\),按照題意模擬。
*P3435 [POI2006]OKR-Periods of Words
若 \(s\) 存在 border,令其最短 border 長度為 \(L\),根據 border 的性質 1 和性質 2(見 常見字符串算法 Part 5 border 論),\(s[1,n-L]\) 就是一個合法的周期。因此只需求出每個點在失配樹上的最淺非 \(0\) 祖先。
P3436 [POI2006]PRO-Professor Szu
細節題。首先,若一個環能夠到達教學樓,那么這個環上的每個點到教學樓的路徑數量都是無窮大。因此建反圖縮點拓撲排序,若一個強連通分量大小 \(>1\) 或有自環則不能入隊。拓撲排序同時記錄路徑數 \(f_i\) 表示從 \(i\) 到 \(n + 1\) 的路徑數量,對 \(36501\) 取 \(\min\)。
但題目沒有保證每個點都能到教學樓,所以需要對非教學樓的點跑一遍拓撲排序。注意此時若強連通分量有自環或者大小大於 \(1\) 是可以入隊的,因為它們沒有到達教學樓的路徑。
最后,若出現沒有入隊的點,說明這個點能夠到達一個能夠到達 \(n + 1\) 的環,因此路徑數無窮大。此外,若 \(f_i > 36500\) 也不符合題意。時間復雜度線性。
*P3437 [POI2006]TET-Tetris 3D
對於一般的區間取 \(\max\) 區間查詢 \(\max\),我們可以用普通帶 lazytag
的線段樹完成。但若要求不能下傳標記(否則空間炸),不能 pushup
(否則時間炸,因為一次 pushup
要進行大小為 \(V\) 的線段樹合並),那就有些棘手了。
一個技巧是標記永久化,在更新路徑上將維護的區間 \(\max\) \(val_i\) 對修改值 \(v\) 取 \(\max\),在所有拆分區間處將懶標記 \(laz_i\) 對 \(v\) 取 \(\max\)。查詢時求遞歸路徑上所有懶標記的最大值,再與拆分區間處維護的區間 \(\max\) 取最大值。
實際意義:\(val_i\) 表示維護的區間 \(\max\),而 \(laz_i\) 表示 沒有被下傳 的修改值的 \(\max\),所以區間 \([l_i,r_i]\) 的最大值為 \(val_i\) 與 \(i\) 到線段樹的根上所有結點的 \(laz_i\) 的最大值。因此查詢時需要整個遞歸路徑的 \(\max laz_i\)。時空復雜度 \(\mathcal{O}(n\log S\log D)\)。
*P3438 [POI2006]ZAB-Frogs
世 界 線 收 束。以前在小 b 那兒做過的題目,現在換種方法解決:設 \(m_{i, j}\) 表示第 \(i\) 行距離 \((i, j)\) 的最近壞點,設 \(f_{i, j}\) 表示距離 \((i, j)\) 的最近壞點,那么有:
寫成 \(m_{k, j} ^ 2 + k ^ 2 = 2ki + (f_{i, j} - i ^ 2)\) 的形式,斜率優化即可。求出距離后並查集維護連通性容易做到 \(\mathcal{O}(nm\alpha)\)。
P3439 [POI2006]MAG-Warehouse
切比雪夫轉曼哈頓裸題。進行 \(x'\gets x + y\),\(y'\gets x - y\) 的變換后兩維獨立,求 \(p\) 使得 \(\sum\limits_{i = 1}^n w_i |i-x_i|\) 最小是經典問題,找帶權重心即可。注意由於兩維重心 \(x, y\) 奇偶性不同導致轉回來的時候坐標出現小數,因此需檢查 \(x + \delta_x\) 與 \(y + \delta_y\),若奇偶性相同則轉回切比雪夫求最小值更新答案,其中 \(\delta_x, \delta_y\in [-1, 1]\)。以及求切比雪夫距離之和時需要 __int128
。時間復雜度是排序的線性對數。
P3440 [POI2006]SZK-Schools
一個新編號只能被一個學校占用,不難想到帶權二分圖匹配。最小費用最大流即可,如果沒有流滿說明無解。時間復雜度玄學,一個非常松的上界是 \(\mathcal{O}(n ^ 2m)\) 即 \(n ^ 4\)。
*P3441 [POI2006]MET-Subway
CF526G 的弱化版。找到直徑一端作為根,長鏈剖分取 \(2l - 1\) 個葉子即可。
P3442 [POI2006]NAJ-The Invasion
比較基礎的凸包題目。
考慮枚舉三角形的三個點,我們必須做到 \(\mathcal{O}(1)\) 判斷三角形內點的價值之和。這可以通過預處理 \(f_{i, j}\) 表示向量 \(\overrightarrow{P_i P_j}\) 逆時針方向與凸包之間形成的區域包含的點的價值之和,然后用總價值減去 \(f_{i, j} + f_{j, k} + f_{k, i}\ (1\leq i < j < k\leq n)\) 得到。由於三角形包含邊界,所以 \(f_{i, j}\) 不包含邊界。
\(f_{i ,j}\) 如何預處理呢?枚舉每個物資 \(Q_k\),順時針二分找到第一個位置 \(p\) 使得 \(\overrightarrow{P_i Q_k}\) 在 \(\overrightarrow{P_i P_j}\) 的逆時針方向,即 \(\overrightarrow{P_iP_j} \times \overrightarrow{P_iQ_k}> 0\),此時所有在 \(p\) 順時針方向直到 \(i-1\) 的所有點 \(j\) 的 \(f_{i, j}\) 都需要加上 \(c_k\)。通過破環成鏈 + 差分做到。
注意特判在頂點上的物資。時間復雜度 \(\mathcal{O}(n(n ^ 2 + m\log n))\)。\(n ^ 3\) 有 \(\dfrac 1 6\) 的常數,可以通過。
*P3443 [POI2006]LIS-The Postman
每條路徑片段的限制形如在片段中出現的相鄰兩條邊必須先后走,因為題目限制一條邊有向邊僅出現一次。
所有限制形成一條邊先后走的關系的鏈(類似 CSP2019 T4 樹上的數),將這條鏈縮成從起點到終點的一條邊,然后跑歐拉回路。最后輸出這條邊時要再展開成鏈,因此要記錄每條鏈上的結點順序。
若限制關系出現環或分叉則無解,這可以通過並查集或鏈表維護。時間復雜度線性對數或線性。
*P3444 [POI2006]ORK-Ploughing
有趣的思維題。考慮到最后必然是行或者列被刪完,所以我們不妨設行被刪完。
接下來,考慮固定左右各刪去多少列,即設 \(f_{l, r}\) 表示還剩 \(l\sim r\) 這些列時,盡量刪行 之后剩下來的行數的區間 \([p_{l, r}, q_{l, r}]\),因為我們要讓行盡快被刪完。
區間 \([p, q]\) 唯一,反證法可證:假設存在另一個區間 \([p', q']\),不妨設 \(q' < q\),那么可以刪到 \([p, q']\),與 “盡量刪” 的定義矛盾。同理,若 \(p < p'\),我們也可以刪到 \([p', q]\)。\(\square\)
考慮如何求出 \(f_{l, r}\)。顯然,它要從 \(f_{l - 1, r}\) 和 \(f_{l, r + 1}\) 轉移過來。如果 \(f_{l - 1, r}\) 最左邊一列能刪掉,即 \(k\geq \sum\limits_{i = p_{l - 1, r}} ^ {q_{l - 1, r}} t_{i, j}\),那么 \(f_{l, r}\) 繼承 \(f_{l - 1, r}\)。同理,若 \(f_{l, r + 1}\) 最右邊一列能刪掉,\(f_{l, r}\) 也可以繼承 \(f_{l, r + 1}\)。任意繼承不會影響復雜度:均攤證明時間復雜度是 \(\mathcal{O}(nm)\)。
同理,假設列被刪完再做一遍上述算法即可得到正確答案。
*P3446 [POI2006]EST-Aesthetic Text
還算有趣的動態規划。遇到區間划分題首先考慮 DP,設 \(f_{i, j}\) 表示以第 \(i\) 個單詞結尾為一行,且這一行長度為 \(j\) 的最小答案,有 \(f_{i, j} = \min\limits_{k = 1} ^ m(f_{p, k} + |j - k|)\),其中 \(p\) 滿足 \(i - p - 1 + \sum\limits_{q = p + 1} ^ i l_q = j\)。直接轉移的復雜度為 \(\mathcal{O}(n ^ 2m)\)(枚舉 \(p\) 算出對應的 \(j\))。
不過注意到很多 \(j\) 都是空值,說明這個定義有些劣。不妨修改定義,設 \(f_{i, j}\) 表示最后一行為 \(i - j + 1\sim i\) 的答案,再設 \(L_{i, j}\) 表示 \(j - 1 + \sum\limits_{p\in [i - j + 1, i]} l_p\) 即 \(i - j + 1\sim i\) 組成一行的長度,那么有:
時間復雜度優化為 \(\mathcal{O}(n^3)\),但仍無法接受。使用拆絕對值的技巧,維護 \(pre_{i, j}\) 表示 \(f_{i, j} - L_{i, j}\),\(suf_{i, j}\) 表示 \(f_{i, j} + L_{i, j}\)。對於 \(f_{i, j}\) 對應的轉移位置 \(i - j\),我們只需找到最后一個位置 \(p\) 使得 \(L_{i - j, p}\leq L_{i, j}\),那么 \(f_{i,j}\) 可以由 \(pre_{i, p}\) 關於 \(p\) 的前綴 \(\min\) 加上 \(L_{i, j}\),以及 \(suf_{i, p+1}\) 關於 \(p\) 的后綴 \(\min\) 減去 \(L_{i, j}\) 得到。
又因為固定 \(i - j\) 時,\(L_{i, j}\) 隨着 \(i\) 增大而增大,這說明 \(f_{i + k, j + k}\) 從 \(i - j\) 處轉移時的 \(p\) 隨着 \(k\) 增加而遞增,因此對每個位置 \(i\) 維護分界點指針即可做到平方。
**P3447 [POI2006]KRY-Crystals
究極神仙題!讀完題目,紛繁復雜的限制讓我們無從下手。從哪個條件作為突破口呢?肯定是最嚴格的異或限制。
異或有性質 \(a \oplus b = c\Rightarrow b = a\oplus c\)。對應到題目中,就是若序列 \(a\) 有 \(n - 1\) 個數確定,則未定數只能等於所有確定數的異或和。這啟發我們思考,有沒有一種可能,未定數對應的限制 \(m_i\) 非常大,以至於無論 \(n - 1\) 個數怎么選,它們的異或和總不大於 \(m_i\),這樣我們就可以很方便地用乘法原理求出答案。
實際上有可能!考慮第 \(i\) 位,假設存在 \(p\) 使得 \(m_p\) 這一位為 \(1\),但 \(a_p\) 為 \(0\),說明若所有數字在第 \(i\) 位及其高位異或和為 \(0\),那么無論其它數字低 \(i - 1\) 位怎么填都符合條件,因為 \(a_p\) 在第 \(i\) 位小於 \(m_p\),所以接下來的低 \(i - 1\) 位沒有限制。
這啟發我們直接枚舉所有 \(a_p\) 與 \(m_p\) 的最短 LCP,即 存在 \(p\) 使得 \(m_p\) 在第 \(i\) 位為 \(1\) 但 \(a_p\) 為 \(0\),且 \(a\) 高於第 \(i\) 位的部分與 \(m\) 相同 的位數 \(i\)。這樣,我們只需把任意一個 \(p\) 的系數變為 \(1\)(因為它依賴於剩余數的異或和),剩下的系數用乘法原理乘起來即可。
具體地,考慮我們關心什么:第 \(i\) 位異或和為 \(0\) 且存在 \(p\)。這啟發我們設計 DP \(f_{j, k, l}\) 表示考慮到第 \(j\) 個數,第 \(i\) 位異或和為 \(k\) 且是否存在 \(p\)。根據乘法原理與實際意義轉移:
若 \(m_j\) 第 \(i\) 位為 \(1\),那么 \(a_j\) 可以選擇 \(0 / 1\):選 \(0\) 的方案數為 \(2^i\),選 \(1\) 的方案數為 \(m_j - 2^i\)。從 \(l = 0\) 轉移到 \(l = 1\) 時,系數為 \(1\),表示欽定 \(j\) 的系數為 \(1\)。
若 \(a_j\) 第 \(i\) 位為 \(0\),則只能選 \(0\) 且方案數為 \(m_j+1\)。
最后,若 \(m\) 比 \(i\) 高的位的異或和為 \(0\) 才能計算當前位貢獻 \(f_{n, 0, 1}\),因為欽定了高位 \(a\) 都取 \(m\)。注意全零序列會被統計到,因此最后答案減 \(1\)。時間復雜度是優秀的線性對數,所以為什么數據范圍這么小?
總結一下,對於位運算相關 有限制 的計數題,首先考慮 最嚴格 的限制,並盡量 獨立每一位,如果做不到就按順序考慮每一位的限制。
*P3448 [POI2006]MIS-Teddies
還算有趣的 DP,感覺難度沒有黑牌。
奇奇怪怪的限制 + 很小的數據范圍,動態規划沒跑了。注意到我們根本不需要知道序列長什么樣,只需每種玩具放的個數以及最后兩個玩具是什么就可以轉移。因此設六維 DP \(f_{i, j, k, l, m, n}\) 表示放了 \(i, j, k, l\) 個 \(A1, A2, B1, B2\),分別標號為 \(0, 1, 2, 3\),最后兩個玩具分別是 \(m\) 和 \(n\) 的方案數,轉移直接枚舉下一個放什么,檢查一下是否符合題意即可。
空間復雜度可通過滾動數組優化。時間復雜度四方,有 \(64\) 倍常數。
*P3449 [POI2006]PAL-Palindromes
神仙題!看到題目,我的想法是如果 \(s_j\) 能接到 \(s_i\) 后面,說明 \(s_j\) 是 \(s_i\) 的前綴。因此,對枚舉每個 \(s_i\) 的每一位 \(p\),求出 \(s_{i}[1,p]\) 在 \(s\) 中的出現次數,以及 \(s_i[p+1,|s_i|]\) 是否是回文串。這可以通過簡單的字符串哈希在線性對數時間內做到。
注意到我們根本沒有用到 \(s\) 是回文串的性質。這好嗎?這不好。我們有一個更強的性質:在 \(s_i, s_j\) 是回文串的前提下,\(s_i + s_j\) 是回文串 當且僅當 它們的 最短回文整周期串相同。充分性顯然。
在證明必要性之前,我們給出一個引理:若長度為 \(n\) 的 回文串 \(s\) 存在 回文 周期 \(p\),則存在長為 \(\gcd(n, p)\) 的 回文整周期。用數學歸納法證明如下:
-
當 \(p\mid n\) 時,顯然成立。
-
設串 \(A = s[1, p]\),\(B = s[n - n\bmod p + 1, n]\),即 \(s = AAA\cdots AB\)。設 \(q = |B|\),顯然 \(q = n\bmod p > 0\)。設 \(B_R\) 表示 \(B\) 翻轉后得到的串。
由於 \(s, A\) 都是回文串,故 \(s = B_RA\cdots AAA\)。因為 \(B\) 是 \(A\) 的前綴,\(B_R\) 也是 \(A\) 的前綴,所以 \(B = B_R\) 即 \(B\) 回文。故 \(s = BA\cdots AA\)。
因為 \(A\) 是 \(BA\) 的前綴,所以 \(A[1, q] = A[q + 1, 2q]\)。同理,\(A[q + 1, 2q] = A[2q + 1, 3q] = \cdots\)。這說明 \(|B|\) 是 \(A\) 的回文周期。
-
這是一個遞歸式的子命題:若長度為 \(p\) 的回文串 \(A\) 存在回文周期 \(q\),則存在長為 \(\gcd(p, q)\) 的回文整周期。若子命題成立,則原命題成立。
-
由於 \(\gcd(n,p) = \gcd(p, n\bmod p) = \gcd(p, q)\),類似輾轉相除法,因此必然出現 \(p'\mid n\) 的情況,此時 \(p' = \gcd(n,p)\)。故原命題成立。
必要性:考慮反證法,設 \(s_i\) 最短回文周期對應的回文串為 \(x\)(注意周期是長度,但為方便說明,下文省略 “對應的”),\(s_j\) 的為 \(y\)。不妨設 \(|x| < |y|\)(\(|x| = |y|\) 時顯然若 \(s_i + s_j\) 回文則 \(x=y\) )。
-
首先,\(x\) 不可能是 \(y\) 某個整周期回文串,否則 \(s_j\) 最短回文周期可以是 \(|x|\),矛盾。
-
當 \(|s_i| < |y|\) 時,因為 \(s_i + s_j = s_iyy\cdots y\),而 \(s_i\) 和 \(s_i + s_j\) 是回文串,所以 \(s_i + s_j = yy\cdots ys_i\)。故 \(y[1, |s_i|] = y[|s_i| + 1, 2|s_i|] = \cdots\),即 \(|s_i|\) 是 \(y\) 的回文周期。
根據引理,這說明 \(y\) 存在回文整周期 \(d = \gcd(|y|,|s_i|) < |y|\),從而有 \(s_j\) 的最短回文周期不大於 \(d\) 即小於 \(|y|\),與 \(y\) 的定義矛盾。
-
當 \(|s_i|\geq |y|\) 時,因為 \(y\) 和 \(s_i + s_j\) 是回文串,所以 \(s_i[1, |y|] = y\)。這說明 \(|x|\) 是 \(y\) 的回文周期。
根據引理,\(y\) 存在回文整周期 \(d = \gcd(|x|, |y|)<|y|\),從而有 \(s_j\) 的最短回文周期不大於 \(d\) 即小於 \(|y|\),與 \(y\) 的定義矛盾。\(\square\)
綜上,我們只需 KMP 求出每個字符串的 \(nxt\) 數組,易證若 \(|s| - nxt_{|s|}\) 整除 \(|s|\) 則 \(s[1, |s|-nxt_{|s|}]\) 是最短回文周期字符串,否則最短回文周期字符串就是 \(s\) 本身。
每個最短回文周期字符串對答案的貢獻為 \(c ^ 2\),其中 \(c\) 表示它作為 \(c\) 個串的最短回文周期字符串出現。為此,我們需要排序並檢查相鄰兩個最短回文周期字符串是否相等。時間復雜度線性對數。
2007
P3452 [POI2007]BIU-Offices
題目相當於求給定圖的補圖的連通塊數量,直接做時間復雜度顯然無法承受。注意到對於當前節點 \(x\),我們只需找到第一個不與 \(x\) 相鄰且沒有被訪問過的節點打上訪問標記並入隊,通過雙向鏈表 + dfs 實現。時間復雜度 \(\mathcal{O}(n + m)\)。dfs 應該做不了。
P3456 [POI2007]GRZ-Ridges and Valleys
將高度相同的相鄰位置連邊,對於每個極大連通塊,若與其相鄰的位置高度均小於連通塊高度,則是山峰。同理,若與其相鄰的位置高度均大於連通塊高度,則是山谷。時間復雜度平方。
P3459 [POI2007]MEG-Megalopolis
轉化題意,求根到某個節點經過的特殊邊數量。考慮維護每個節點的答案,一次修改就是子樹 \(-1\),dfs 序拍平,BIT 維護,時間復雜度線性對數。
*P3462 [POI2007]ODW-Weights
任意兩個砝碼重量互成倍數說明最多只有 \(\log V\) 種重量不同的砝碼。貪心能放大的就放大的(因為大的一定能被換成小的,但如果放小的讓大的沒地方放,可能導致答案更劣),最后再調整。調整的方法即從大到小枚舉每一種重量,如果有比它輕的砝碼沒放完,就把它去掉,然后放更小的砝碼。類似上面的貪心,去掉后優先從大往小放。時間復雜度線性對數。
*P3463 [POI2007]EGZ-Driving Exam
關鍵性質:如果 \(i\) 能到最左邊,那么 \(i - 1\) 也能。因此,能夠到達所有道路的初始位置一定是一段區間 \([l, r]\),滿足 \(1\sim r\) 能到最左邊但 \(r + 1\) 不能,且 \(l \sim n\) 能到最右邊但 \(l - 1\) 不能。
設 \(pre_i\) 表示使 \(1\sim i\) 能到最左邊,最少需要修建多少條路。明眼人可以看出這是 \(i\) 減去 \(1\sim i\) 的 LDS,但是我沒有看出來(大霧)。提供一個新的思路:考慮枚舉從 \(i\) 向左邊的所有道路,設其高度為 \(k\),我們設 \(f_{i, k}\) 表示 \(i\to i - 1\) 走的道路的高度為 \(k\) 時,走到 \(1\) 最少需要新建多少條路。再枚舉下一步走的 原有 的道路是哪一條,有轉移方程
初始值 \(f_{1, m} = 0\)。后面的 \(i - j - 1\) 是因為根據定義,從 \(i - 1\) 到 \(j\) 走的都不是原有道路,因此要新建 \(i - j - 1\) 條道路。\(p \geq k\) 的原因顯然。將貢獻拆成 \((f_{j, p} - j) + (i - 1)\),變成一個經典的二維數點,\(i\) 的有序性(從小到大枚舉位置)自然地使用掃描線,把問題降了一維。我們需要支持單點修改,以及查詢后綴最小值。由於查的是后綴,信息不需要可減,所以樹狀數組維護即可。而 \(pre_i\) 顯然就是 \(\min f_{i, k}\)。
對於 \(suf_i\) 同理,轉移方程變成了 \(f_{i, k} = \min\limits_{i < j \leq n \land p\geq k} f_{j, p} + (j - i - 1)\),同樣用 BIT 維護。
根據一開始的結論,區間 \([l, r]\) 合法當且僅當 \(suf_l + pre_r \leq k\),因為向左邊和向右邊的道路獨立,\(suf_l\) 和 \(pre_r\) 只是做簡單的加法。注意到 \(pre\) 具有單調不降,\(suf\) 具有單調不升的性質,因此考慮按從小到大的順序枚舉 \(r\),合法的 \(l\) 隨着 \(r\) 的遞增,顯然單調不減,只需用指針維護即可,該部分時間復雜度線性。
總時間復雜度是樹狀數組的線性對數。實際上 LIS/LDS 和我的動態規划應該是在干同一件事情 qwq,只不過我想復雜了。
P5925 [POI2007]Gaz
若天然氣井 \(x_1, y_1\) 和中轉站 \(x_2, y_2\) 配對,對答案的貢獻為 \(x_2 - x_1 + y_1 - y_2\)。因此答案為所有天然氣井的 \(y - x\) 之和加上中轉站的 \(x - y\) 之和。
2008
P3467 [POI2008]PLA-Postering
不難發現寬度 \(d_i\) 無用。考慮若 \(w_{i - 1} > w_i\),那么 \(w_{i - 1}\) 前面必然要貼一張海報,因此用單調棧維護,時間復雜度線性。
P3475 [POI2008]POD-Subdivision of Kingdom
合法的分割方案最多僅有 \(\dbinom {26}{13}\approx 10 ^ 7\) 種,因此 dfs 枚舉每個數是否被分進第一個集合。直接使用 C++ 自帶的 __builtin_popcount
比手寫 popcount
快不少。
P3478 [POI2008] STA-Station
換根 DP 板子題。
2009
P3486 [POI2009]KON-Ticket Inspector
由於我們只關心上一次檢票是在什么時候,考慮設計動態規划狀態 \(f_{i, j}\) 表示第 \(i\) 次檢票在第 \(j\) 站時最多能夠查到多少人的票,轉移方程即
這是因為新的被查票的人必須得從第 \(k\) 站之后上(否則之前就被查了),在過了第 \(j\) 站之后下(否則查不到)。直接做復雜度 \(\mathcal{O}(k n ^ 4)\),顯然無法接受。
\(t\)D / \(1\)D 動態規划通常設計貢獻函數 \(w\),預處理或推柿子從而快速計算 \(w\)。設 \(w(j, i)\) 表示 \(\sum\limits_{j < p \leq i < q} a_{p, q}\),朴素預處理后復雜度變成 \(kn ^ 2 + n ^ 4\),仍然無法接受。
考慮更快地預處理:我們沒有必要為每個 \(w\) 都重新算一遍,可以利用已經算過的結果遞推。不難發現 \(w(j, i) = w(j + 1, i) + \sum\limits_{q > i} a_{j + 1, q}\),這樣即可做到 \(n ^ 3\),再加個后綴和優化,預處理就是平方的。因此時間復雜度 \(\mathcal{O}(kn ^ 2)\)。
P3487 [POI2009]ARC-Architects
POI 真的很喜歡出 單調隊列!
字典序最大給予我們貪心的思路,即優先選擇最大的數字肯定更優,若數字相同則盡量選更前面的,因為這樣剩下來的選擇就更多。如 \([9,7,9,6]\),選前面的 \(9\) 就比選后面的 \(9\) 好。
但是有 \(b_i < b_{i + 1}\) 的限制,說明如果我們選最大的,可能導致后面沒法選了。因此不妨設我們在選 \(b_i\),我們只能從下標為 \([b_{i - 1} + 1, k - i + 1]\) 的數當中挑選,因為如果 \(b_i\) 再大一點,那么無論如何我們都選不齊 \(k\) 個數。實現就是經典滑動窗口,若當前數等於單調隊列隊尾則不彈出,保證了相同數優先選擇更前面的。時間復雜度線性。
P3492 [POI2009]TAB-Arrays
因為任何操作不改變每一行和每一列由哪些數組成,只是改變它們的順序,故只需判斷 \(a, b\) 每一行和每一列的數字能否對應上,即對於 \(a\) 的每一行 \(a_i\),存在 \(b\) 的某一行 \(b_j\),使得 可重集 \(\{a_i\} = \{b_j\}\),且一行 \(a_i\) 與一行 \(b_j\) 唯一對應,對於列同理。
由於數字無序,可以排序后哈希(如字符串哈希),也可以使用不依賴於數字順序的哈希方法(如 \(\sum a_{i, k} + \prod a_{i, k}\)),再看 \(a, b\) 的每一行(列)的哈希值是否能夠一一對應(簡單的檢查方法是排序后相同排名的數相等)。前者時間復雜度是 \(\mathcal{O}(nm(\log n + \log m))\),后者時間復雜度是 \(\mathcal{O}(nm + n\log n + m\log m)\)。效率差距較大。
2010
P3496 [POI2010]GIL-Guilds
找出原圖任意一棵生成森林黑白染色,若存在孤立點則無解,時間復雜度線性。
P3498 [POI2010]KOR-Beads
什么哈希和哈希表水題,時間復雜度是調和級數的 \(\mathcal{O}(n\ln n)\)。后綴數組被完全碾壓了,嚴格 \(\log ^ 2\) 的玩意兒(大霧)。
P3500 [POI2010]TES-Intelligence Test
什么子序列自動機裸題。設每個序列 \(j\) 第一個沒有被匹配的元素為 \(c_j\),位位置為 \(p_j\),依次遍歷序列 \(a\) 中的每個元素 \(a_i\),將 \(c_j = a_i\) 的所有 \(j\) 的匹配位置 \(+1\),即 \(p_j\gets p_j + 1\),\(c_j\gets b_{j, p_j}\),可以用 vector 或鄰接鏈表輔助實現。若最終 \(p_j > |b_j|\) 則是 \(a\) 的子序列,否則不是。這是 離線 做法。若在線容易 vector + 二分實現。
P3501 [POI2010]ANT-Antisymmetry
直接二分 + 哈希太 low 了,借鑒 manacher 的思路,我們對每個位置(以兩個字符之間作為回文中心)求出最長 anti-symmetry 半徑,注意到這個類似 manacher,也是可以記錄最右邊的回文區間,快速繼承和擴展做到均攤線性。
*P3503 [POI2010]KLO-Blocks
多組詢問要求我們必須使用線性做法,而一個區間滿足條件等價於其平均值 \(\geq k\),即令 \(s\) 表示 \(a - k\) 的前綴和,則 \(s_{l - 1} \leq s_r\) 是區間合法的充要條件。
乍一看沒啥思路,似乎要數據結構維護,因為我們需要查詢 \(\leq s_i\) 的所有數的最小下標(\(i\) 之后的位置沒有貢獻,可以不管)。但就算這樣也得排序。
觀察性質,注意到若 \(s_i < s_j\) 且 \(i < j\),那么 \(j + 1\) 不會作為區間 左端點 出現,因為 \(i + 1\) 更優。同理,若 \(i\) 不會作為區間 右端點 出現,因為 \(j\) 更優。換句話說,只有 前綴最小值 的位置才會作為區間左端點,后綴最大值 的位置才會作為區間右端點。
因此,兩遍單調棧求出前綴最小值和后綴最大值對應的位置,根據單調性只需用兩個指針維護。具體地,從左到右遍歷每個前綴最小值,找到最右邊的一個后綴最大值使得該最大值不小於當前的前綴最小值。由於前綴最小值在不斷減小,故其對應的后綴最大值的下標也單調不降,用指針維護即可。時間復雜度 \(\mathcal{O}(mn)\)。
P3507 [POI2010]GRA-The Minima Game
DP + 博弈趣題。一個人肯定取剩下來所有數中最大的 \(k\) 個數,否則會把大數留給對手,不優。因此,設 \(f_i\) 表示還剩下 \(i\) 個數時,先手能達到的最大分數,枚舉選完還剩下幾個,有轉移
注意 \(k\) 是從小到大排過序的,\(f_n\) 即答案。用一個變量維護即可。時間復雜度線性。
P3509 [POI2010]ZAB-Frog
首先 two-pointers 求出距離每個點第 \(k\) 小的點,連出基環內向森林,求每個點走 \(k\) 步到哪個點。可以快速冪線對解決,但是沒有直接拓撲排序找環 + dfs 優美。靜態 \(k\) 級祖先直接用棧維護就好了。時間復雜度線性。
P3512 [POI2010]PIL-Pilots
POI 真的很喜歡出 單調隊列!直接 two-pointers + 兩個單調隊列就做完了。時間復雜度線性。
2011
*P3514 [POI2011]LIZ-Lollipop
元素權值僅有 \(1\) 和 \(2\) 一定是非常重要的限制。考慮固定左端點 \(l\),右端點 \(r\) 從 \(l\to n\) 的過程。設 \([l, r]\) 之和為 \(v_{l, r}\),容易證明若 \(1 \leq k < s\) 且 \(k\) 不能被表示為以 \(l\) 開頭的某個子串和,則 \(k + 1\) 一定可以被表出。否則至少存在一個元素權值不小於 \(3\)。
因此,考慮找到最長的后綴 \([l, n]\) 使得 \(s_l = \tt W\)(即找到最小的 \(l\) 使得 \(s_l = \tt W\)),則根據上述性質,\(1\sim v_{l, n}\) 一定全部能被表示出來,因為若 \(2\leq k < v_{l, n}\) 不能被以 \(l\) 開頭的某個子串和表出,則 \(k + 1\) 一定能被以 \(l\) 開頭的某個子串和表出,所以 \(k\) 一定能被以 \(l + 1\) 開頭的某個子串和表出。同理,最長的前綴 \([1, r]\) 同樣滿足該性質。
因此,求出開頭和末尾的連續的 \(2\) 的個數 \(be, ed\)。若 \(be \leq ed\),說明 \([l, n]\) 之和大於 \([1, r]\) 之和,用后綴來做。否則用前綴來做。可以通過翻轉序列避免分類討論,因此不妨設 \([l, n]\) 之和更大。
設 \(buc_k\) 表示 \([l, buc_k]\) 之和等於 \(k\)。注意 \(buc_k\) 可能不存在,但此時根據上述性質,\(buc_{k + 1}\) 存在。
- 若詢問的 \(k \leq v_{l, n}\),則若 \(buc_k\) 存在,輸出 \(l, buc_k\)。否則輸出 \(l + 1, buc_{k + 1}\)。
- 否則,若 \(k \leq v_{1, n}\) 且 \(k\) 與 \(v_{l, n}\) 的奇偶性相同(因為接下來只能讓 \(l\) 往左移,每次添加 \(2\)),則輸出 \(l - \frac{k - v_{l, n}} 2, n\)。
- 否則無解。
時間復雜度線性。
*P3518 [POI2011]SEJ-Strongbox
若 \(v\) 在群里,則所有 \(\leq n\) 且是 \(\gcd(v, n)\) 的倍數的數也在群里。這是因為 \(kv \bmod n\) 取到了所有這樣的數。證明:設 \(d = \gcd(v, n)\),\(d\mid t\) 且 \(t\) 不在群里,這意味着 \(kv \equiv t\pmod n\) 即 \(kv + yn \equiv t \pmod n\) 無解,根據裴蜀定理,它等價於 \(\gcd(v, n) \nmid t\) 即 \(d\nmid t\),矛盾。證畢。
因此,考慮枚舉這個 \(d = \gcd(v, n)\),若合法則答案即 \(\max\dfrac n d\),即我們需要找到最小的合法的 \(d\)。如何判斷合法:不妨設 \(d_i = \gcd(m_i, n)\),\(d\) 首先得是密碼與 \(n\) 的 \(\gcd\) 即 \(d_k\) 的因數,其次任何 \(d_i\ (1\leq i < k)\) 不能是 \(d\) 的倍數。
考慮后者限制:給所有 \(d_i\ (1\leq i < k)\) 打上標記,從大到小枚舉 \(n\) 的每個因數 \(c\),若 \(c\) 被打上標記,則 \(\dfrac{c}{p_j}\) 也應被打上標記(其中 \(p_j\) 表示能整除 \(c\) 的 \(n\) 的質因子),表示若 \(c\) 是某個 \(d_i\ (1 \leq i < k)\) 的因數,則 \(\dfrac c {p_j}\) 顯然也是。
剩下來沒有被打上標記的所有 \(n\) 的因數 \(d\),若 \(d\) 能被 \(d_k\) 整除則合法。找到最小的這樣的 \(d\),則答案為 \(\dfrac n d\)。
打標記的過程用哈希表實現,時間復雜度 \(\mathcal{O}(\sqrt n + k\log n + d(n)\omega(n))\)。\(\omega(i)\) 表示 \(i\) 的質因數個數。
P3520 [POI2011]SMI-Garbage
設 \(f(i)\) 表示以 \(i\) 為一端的需要經過的邊的數量。對於一條回路,所有點度數均為偶數,因此一次操作后 \(f(i)\) 的奇偶性不變。故若存在 \(i\) 使得 \(f(i)\) 是奇數,則無解。否則,注意到有解是需要經過的邊形成的圖的每個連通塊均存在歐拉回路的充要條件,對這張圖跑一遍歐拉回路。由於要求不能經過相同的點,而路徑上相同的點之間也一定是回路,所以借助棧把相同的點之間的回路彈出。時間復雜度 \(\mathcal{O}(n + m)\)。
對於不需要經過的邊,可以直接忽略,這是因為是否有解與這些邊無關:如果 \(f\) 均為偶數,我們必然能構造出一種不經過需要修改的邊,反之無解。
*P3523 [POI2011] DYN-Dynamite
首先二分答案,問題轉化為若選一個點能覆蓋距離 \(\leq mid\) 的點,要覆蓋所有關鍵點至少要選多少個點。直接貪心似乎不太行,考慮設 \(f_i\) 表示 \(i\) 子樹內最遠的未被覆蓋的 關鍵點 與 \(i\) 的距離,\(g_i\) 表示 \(i\) 子樹內最近的被選擇的節點與 \(i\) 的距離。
\(f\) 初始值為 \(-\infty\),\(g\) 初始值為 \(\infty\)。若 \(f_u\) 本身是關鍵節點,則初始化 \(f_u = 0\)。轉移時 \(f_u = \max\limits_{v\in \mathrm{son}(u)} f_v + 1\),\(g_u = \min\limits_{v \in \mathrm{son}(u)} g_v + 1\)。
由於若 \(f_u + g_u \leq mid\),則 \(u\) 子樹內對應的最遠未被覆蓋的關鍵點可以被覆蓋,因此可忽略,即令 \(f_u = -\infty\)。否則,若 \(f_u = mid\) 或 \(u\) 為 根節點 且 \(f_u > 0\),則需要選擇 \(u\),令 \(g_u = 0\),\(f_u = -\infty\)。
時間復雜度線性對數。預處理 dfs 序后每次 DP 可以直接遞推,不用遞歸,有效減小常數。
2012 (2021.12.14-12.19)
*P3530 [POI2012]FES-Festival
很好,限制非常差分約束。建出圖來,先跑一遍負環判無解。但如何滿足不同的 \(t\) 值數量最大呢?差分約束顯然無法解決這樣的問題。然后就不會了(大霧)。
首先,不同 SCC 之間獨立,因為我們可以將兩個 SCC 之間的距離拉得任意遠。而一個 SCC 內部的答案就是任意兩點最短路徑的最大值 \(+1\):使最短路距離增加的只有一類邊,而一類邊的邊權僅有 \(1\),因此若 \(u\to v\) 的最短路徑 \(w\),那么從 \(u\to v\) 的路徑上所有點必然取遍了 \(t_u\sim t_{v}\) 這 \(w+1\) 個值。
由於圖是稠密圖,因此使用 Floyd 算法求解任意兩點之間的最短路。答案即每個 SCC 的答案之和。時間復雜度三方。
P3531 [POI2012]LIT-Letters
一開始看錯題咧!看成可以交換任意兩個字符咧!不過也可以做,而且復雜度線性。
設 \(a_i\) 在交換后移動到了位置 \(p_i\),則題目即求使得 \(a_i=b_{p_i}\) 的 \(p\) 的最小逆序對數量。顯然,兩個相同字符的相對位置不變。即若 \(a_i=a_j\ (i<j)\),那么不會出現 \(p_i>p_j\)。否則交換 \(p_i,p_j\) 更優,因為可以減小逆序對數量。
因此,\(a\) 中的每個字符唯一對應了 \(b\) 的一個位置,求出 \(p\) 后樹狀數組求逆序對即可。時間復雜度線性對數。
*P3532 [POI2012]ODL-Distance
考慮在 \(i\) 和 \(p\times i\ (p\in \mathbb{P})\) 之間連邊,題目相當於在這張圖上撒 \(n\) 個關鍵點,求距離每個關鍵點最近且非本身的關鍵點的最小編號。對每個點記錄距離該點最近和第二近的關鍵點距離與編號,一遍 BFS
即可,但是常數太大,不開 O2 難以通過。
設 \(\omega(i)\) 表示 \(i\) 的質因子個數,則 \(\mathrm{dis}(i,j)=\omega(i)+\omega(j)-2\omega(\gcd(i,j))\)。考慮枚舉 \(d=\gcd(i,j)\),那么減號后面的部分就確定了,對於一個固定的 \(i\),我們顯然要讓 \((\omega(j),buc_j)\) 這一二元組最小,其中 \(buc_j\) 表示 \(a\) 值為 \(j\) 的最小位置。
考慮枚舉 \(d\) 的倍數 \(kd\),求出 \(\min_{k\geq 1,kd\leq r}(\omega(kd),buc_{kd})\),設為 \((x,y)\) 以及取到最小值的位置為 \(td\)。 那么對於所有 \(k\neq t\),我們用 \(td\) 和 \(kd\) 互相更新。\(kd\) 就相當於上面的 \(i\),而 \(td\) 充當了使得 \((\omega(j),buc_j)\) 最小的 \(j\)。
每個 \(\gcd\) 都會被枚舉到,因此算法正確。時間復雜度是調和級數的線性對數。由於小常數,成功拿到了最優解(2021.12.19)。
P3533 [POI2012]RAN-Rendezvous
定義 \(i\) 的祖先表示從 \(i\) 一直走出邊遇到的第一個在環上的結點,這個可以通過一遍 dfs 處理得到。處在同一子樹(即奇環內向樹的環上每個結點拖着的 “尾巴”,是一棵樹)內的詢問 \(x,y\) 就是樹上 LCA,預處理倍增數組。
除去上一種情況,若 \(x,y\) 根本不在同一棵基環樹上,顯然無解,否則我們先跳到 \(x,y\) 的祖先 \(anc_x,anc_y\),有兩種選擇:\(anc_x\) 順着環走到 \(anc_y\),或者 \(anc_y\) 順着環走到 \(anc_x\)。兩種方案按照規則取更優的那個即可。時間復雜度線性對數。
*P3534 [POI2012]STU-Well
二分答案。對於固定的 \(z\),首先考慮沒有 \(x_k=0\) 的限制。
因為 \(|x_i-x_{i+1}|\leq z\) 可寫成 \(x_i\leq x_{i-1}+z\ (2\leq i\leq n)\) 以及 \(x_i\leq x_{i+1}+z\ (1\leq i<n)\) ,故我們只需從左往右掃一遍 \(x_i\gets \min(x_i,x_{i-1}+z)\),從右往左掃一遍 \(x_i\gets\min(x_i,x_{i+1}+z)\),然后求出原 \(x_i\) 與新 \(x'_i\) 之間的差 \(d=\sum\limits_{i=1}^n x_i-x'_i\)。
正確性(分為合法性與最小性)證明:
- 合法性:因為 \(x_{i-1}+z\) 操作進行完畢后滿足 \(x_i\leq x_{i-1}+z\),而 \(x_{i+1}+z\) 操作后滿足 \(x_i\leq x_{i+1}+z\),且不會破環 \(x_i\leq x_{i-1}+z\) 的性質(因為 \(z\) 非負),得證。
- 最小性:對於 \(x_{i-1}+z\) 操作,若 \(x_i> x_{i-1}+z\),我們不得不用 \(x_i-x_{i-1}-z\) 的代價填平 \(i\) 這個位置,否則不滿足條件。\(x_{i+1}+z\) 同理。
接下來考慮 \(x_k=0\) 的限制,顯然還要用 \(z\times |i-k|\) 更新 \(x_i\),但我們沒有足夠的時間對每個 \(k\) 都這樣暴力計算。稍作轉化,我們就是要找到所有這樣的 \(p\) 使得 \(x_p > z\times |k - p|\),然后將代價加上 \(x_p - z\times |k - p|\)。
考慮 \(k\) 變為 \(k+1\) 的過程,\(k\) 左邊的位置 \(i\) 的 \(z\times (k-i)\) 會增加,即限制放寬,那么第一個 \(x_i > z\times (k-i)\) 的位置 \(l\) 會向右移動。同理,對於 \(k\) 右邊的位置 \(i\),最后一個 \(x_i > z\times (i-k)\) 的位置 \(r\) 也會向右移動(因為限制變嚴格了)。
同時,我們知道 \(l\sim r\) 的區間內所有位置都有 \(x_i > z\times (k-i)\),以及區間外的位置都有 \(x_i\leq z\times (k-i)\)(否則會出現相鄰兩個數之差的絕對值大於 \(z\) 的情況,因為我們是用斜率絕對值為 \(k\) 的直線去切這個 “山峰”,而任意位置的斜率絕對值不超過 \(k\),故切到的一定是一段區間),所以可以用前綴和與等差數列求和公式快速計算 \(k\) 處的答案。時間復雜度 \(\mathcal{O}(n\log x)\)。
P3535 [POI2012]TOU-Tour de Byteotia
先將所有 \(u,v>k\) 的邊 \((u,v)\) 合並,剩下來所有邊能加就加,用並查集維護連通性,時間復雜度線性對數。想了好一會才會做(小霧)。
P3536 [POI2012]BON-Vouchers
注意到對於一個固定的 \(x\),我們只關心前 \(\dfrac {\max b_i}x\) 個需求為 \(x\) 的顧客,便可斷言接下來需求為 \(x\) 的顧客不可能拿到代金券,這一點顯然。
因此,若當前需求為 \(x\) 的顧客數量 \(c_x>\dfrac{\max b_i}x\),那么可以跳過剩下來所有這樣的顧客。直接暴力模擬,時間復雜度是調和級數求和產生的 \(\mathcal{O}(b\ln b)\),可以接受。
*P3537 [POI2012]SZA-Cloakroom
好題,一開始一直在想 \(\dfrac {nk\log n}{\omega}\) 的 \(0/1\) 背包可行性做法,發現無論如何都不可做。但是背包問題並不一定只能裝 \(0/1\),我們要充分發揮 \(f_i\) 的值域帶來的信息。
由於背包不可刪除,所以按順序將物品加入背包方便回答,故將詢問離線處理。
設 \(f_i\) 表示要用左端點小於當前位置 \(p\) 的所有物品組合出價值 \(i\),所需物品右端點最小值的最大值。其中 \(p\) 是不斷遞增的,與此同時回答對應的詢問。
不妨設要加入 \((c_i,a_i,b_i)\),根據我們的策略有 \(a_i\) 遞增,轉移方程如下:
對於一次詢問 \((k_j,l_j,r_j)\ (l_j=s_j,r_j=s_j+m_j)\),顯然只能用 \(a_i\leq l_j\) 的物品,因此對於在加入 \(a_i\) 之前先要回答所有 \(l_j<a_i\) 的詢問才能保證正確性。在此基礎上,若 \(f_{k_j}>r_j\) 說明可行,否則不可行,這一點結合 \(f\) 的定義容易理解。
綜上,時間復雜度 \(\mathcal{O}(nk+q\log q)\)。
P3538 [POI2012]OKR-A Horrible Poem
\(s\) 有長為 \(p\) 的周期 \(\Leftrightarrow\) \(s\) 有 \(|s|-p\) 的 border。因此,枚舉區間長 \(r-l+1\) 的所有因數 \(d\) 判斷是否有 \(|s|-d\) 的 border 即可。時間復雜度 \(\mathcal{O}(nd(n))\)。
由於若 \(p\) 是周期,那么 \(kp\ (kp\mid |s|)\) 也是周期,因此可以不斷除以 \(|s|\) 的質因數判斷,即從小到大枚舉所有 \(|s|\) 的質因數 \(d\),不斷將 \(p\) 除以 \(d\) 直到不是周期或不能整除位置。時間復雜度 \(\mathcal{O}(n\omega(n))\),拿到了最優解(2021.12.19)。
*P3539 [POI2012]ROZ-Fibonacci Representation
設 \(f_k\) 為答案,可以證明在 \(k\) 的最小斐波那契表示(題目定義)中,必然出現 \(fib_p\) 或 \(fib_{p+1}\),其中 \(fib_p\leq k\) 且 \(p\) 最大(一開始的思路),預處理 \(k\) 較小時的答案就可以玄學復雜度爆搜了。
甚至可以證明若 \(k-fib_p\leq fib_{p+1}-k\) 則選 \(fib_p\) 更優,反之選 \(fib_{p+1}\) 更優,這樣貪心的復雜度是對數,真是驚為天人。不太會證明(大霧),具體可以看洛谷題解區 這篇博客。
*P3540 [POI2012]SQU-Squarks
將給出的 \(s_i\) 和要求的 \(x_i\) 都從大到小排序,\(s_1=x_1+x_2\),\(s_2=x_1+x_3\),這一點顯然。
先考慮已知一些數時,如何推出剩下來的數:假設 \(x_1\sim x_r\) 已知,它們兩兩相加可以形成一些和 \(t_j\),用可重集 \(s\) 減去可重集 \(t\),我們能得到一個最大數 \(s_p\),它只能是 \(x_1+x_{r+1}\) 的和,否則與 \(s_p\) 的最大性違背。
因此,我們斷言如果確定 \(x_1\),那么可以在 \(\mathcal{O}(n^2\log n)\) 的時間內得到整個 \(x_i\):找到可重集 \(s\backslash t\)(\(t\) 的定義如上)中最大的數 \(s_p\),反推出 \(x_{r+1}\),用 \(x_{r+1}\) 與 \(x_1\sim x_r\) 的和更新 \(t\),再找到下一個最大的 \(s_{p'}\in s\backslash t'\) 反推出 \(x_{r+2}\),以此類推。根據 \(s_p\) 的單調性可以用指針維護 \(p\)。\(\log\) 由用 \(x_{r+1}+x_i\) 通過 map
打標記產生。特別的,若求出的 \(x_{r+1}\geq x_r\) 或 \(x_{r+1}\leq 0\) 或 \(t\nsubseteq S\) 則欽定的 \(x_1\) 無解。
接下來考慮如何求 \(x_1\):注意到 \(x_2+x_3\) 僅有可能小於 \(x_1+x_i\ (2\leq i\leq n)\),因此 \(x_2+x_3\) 在從大到小排過序后的 \(s\) 中下標不會超過 \(n\)。考慮直接枚舉這個下標從而解出 \(x_1,x_2\) 和 \(x_3\)。
綜上,時間復雜度三方對數。由於大部分下標很快無解,因此常數非常小。
**P3542 [POI2012]PEN-Salaries
大大大大大大大神仙題!我初始的想法是對整棵樹進行一遍 dfs,將所有兒子按照 \(z\) 從小到大排序,先考慮 \(z\) 非零的那些點,若已經處理過的子樹大小之和 \(s\) 加上當前兒子 \(v\) 的子樹大小等於 \(z_v\),說明 \(v\) 的子樹內的值域唯一確定,為 \([s+1,z_v]\),對 \(v\) 進行 dfs,否則直接返回。這保證被深搜到的結點的值域被唯一確定,而兒子的值域確定建立在父親的值域確定基礎上,因此遇到第一個不符合的子結點就要立刻返回。
很顯然,這樣是錯的。原因是我們沒有考慮到已經被欽定的 \(z\) 值。例如 \(z\) 值較大的結點 \(v\) 有較小 \(z\) 值的兒子 \(w\),當我們考慮 \(v\) 父親的所有子結點時,就不會將 \(z_w\) 的占位計算在內。
一個神仙想法:考慮每個結點的最大可能 \(z\) 值 \(mx_i\)。記 \(pre_i\) 表示 \(\leq i\) 的最大的沒有被欽定的 \(z\) 值,這可以通過對於所有被欽定的 \(z\) 值令 \(pre_z=z-1\),然后 \(i\) 從小到大掃一遍 \(pre_i=pre_{pre_i}\) 預處理出來。那么 \(mx_i\) 即:
記 \(sum_i\) 表示 \(cnt_i\) 即 \(mx\) 值等於 \(i\) 的數的個數的前綴和,由於保證有解,故 \(sum_i\leq i\)。我們斷言 \(mx\) 值為 \(i\) 的結點的 \(z\) 值可以被欽定為 \(i\) 當且僅當 \(sum_i=i\) 且 \(sum_{i-1}=i-1\)。這是因為若一個或多個 \(mx\) 值對應多個空余的 \(z\) 值,則它們全都不能被確定,或者說 \(sum_{i-1}=i-1\) 說明前 \(i-1\) 個值已經被 \(i-1\) 個位置內部消化,就算這 \(i-1\) 個位置沒有唯一確定一個 \(z\) 值,后面的位置的 \(z\) 值也不可能 \(\leq i-1\)(否則就無解了)。那么就做完了,時間復雜度線性,憑借小常數拿到了最優解(2021.12.19)。
**P3543 [POI2012]WYR-Leveling Ground
好題!區間操作轉化為差分數組 \(d_i\) 的端點操作。一次 \(+a\) 可以和一次 \(-a\) 相抵消,因為若 \(+a\) 的位置在 \(-a\) 位置之前,就是區間 \(+a\),否則就是區間 \(-a\)。同理,\(+b\) 和 \(-b\) 可以相抵消。
首先考慮對每個差分值單獨求解,即解不定方程 \(ax+by=d_i\)。設 \(d=\gcd(a,b)\),若 \(d\nmid d_i\) 則無解,這是裴蜀定理。否則在一開始調用一次 exgcd
算法解得 \(ax+by=d\) 的一組特解,再通過對每個 \(d_i\) 乘上 \(\dfrac {d_i} d\) 得到 \(ax+by=d_i\) 的特解。
由於一個 \(ax_i+by_i=d_i\) 的貢獻為 \(|x_i|+|y_i|\),而最終答案(首先不考慮可行性)為所有這樣的貢獻之和除以 \(2\)(因為兩兩配對)。因此嘗試根據特解找到 \(|x_i|+|y_i|\) 最小的特解:若 \(|x_i|\) 不是最小且 \(|y_i|\) 不是最小,那么 \(|x_i|+|y_i|\) 必然不是最小,因此我們只需要檢查 \(x_i\) 和 \(y_i\) 分別取到最小非負整數和最大負整數的情況即可。
當前的 \(\sum |x_i|+|y_i|\) 除以 \(2\) 是答案的下界,但並不能保證可行性,因為我們需滿足 \(X=\sum x_i=0\)(兩兩配對)。由於當 \(X=0\) 時必然有 \(Y=0\),所以只需考慮 \(X\)。
根據特解的形式 \(\begin{cases}x=x'+\dfrac {kb}d\\y=y'-\dfrac {ka}d\end{cases}\),當 \(X < 0\) 時,我們需要進行 \(\dfrac {Xd}b\)(一定是個整數,因為差分數組之和為 \(0\))次將某個 \(x_i\) 加上 \(\dfrac b d\),並將其對應的 \(y_i\) 減去 \(\dfrac a d\)。\(x>0\) 時分別為減去 \(\dfrac b d\) 和加上 \(\dfrac a d\)。稱這樣的操作為對 \(i\) 進行一次調整,調整的代價即新的 \(|x'_i|+|y'_i|\) 減去 \(|x_i|+|y_i|\)。
容易證明對一個數調整的代價隨着調整的次數增加,僅在 \(x_i\) 或 \(y_i\) 改變符號時增加,其它時候不變,因此我們可以用一個堆維護這個過程:每次取出代價最小的 \(i\) 並彈出,在需求次數與不改變符號的前提下盡可能多地調整。若經過調整,需求次數為 \(0\) 則算法結束,否則將新的調整代價壓入堆。這樣的時間復雜度是嚴格 \(\mathcal{O}(n\log n)\),因為 \(x_i,y_i\) 其中任意一個改變符號的才會使代價改變,一共會最多發生 \(2n\) 次,因此我們最多會向堆內壓入 \(3n\) 個數。
一個奇妙的性質是 \(\dfrac {Xd}b\) 在 \(\mathcal{O}(n)\) 級別(根據 \(\sum d_i=0\) 感性理解,不會證明),這使得我們可以從堆中取數時僅進行一次調整就塞回去。時間復雜度也是線性對數。
啟發:我們可以嘗試先忽略問題的一些限制從而得到基本的解法,然后在此基礎上考慮限制,進一步求解問題。
*P3544 [POI2012]BEZ-Minimalist Security
每個連通塊獨立,單獨考慮。對於一個連通塊 \(G=(V,E)\),顯然 \(|E|\geq |V|-1\),故其自由度 \(\leq 1\),即一旦欽定連通塊內任何一個 \(q_i=p_i-z_i\),則整個連通塊確定。
不妨將連通塊內的點編號為 \(1\sim |V|\),考慮用 \(q_1\) 表示 \(q_2\sim p_{|V|}\)。根據題目的限制 \(q_u+q_v=w\),我們知道最后每個 \(q_i\) 都能被寫成 \(k_iq_1+c_i\) 的形式,其中 \(k_i=\pm 1\)。因此,找到 \(G\) 的任意一棵生成樹,求出 \(k_i\) 和 \(c_i\)。
與此同時,對於非樹邊 \((u,v,w)\),若 \(k_u\) 與 \(k_v\) 相同,說明我們能解出 \(q_1\)。此時可以判斷無解:有兩條非樹邊解得的 \(q_1\) 不同,或 \(q_1\) 不是整數(即 \(2\nmid w-k_u-k_v\)),或 \(q_1\) 不在 \([0,p_1]\) 范圍內。相反,若 \(k_u\) 與 \(k_v\) 不同,則需檢查 \(c_u+c_v=w\)。上述操作可以一遍 DFS
完成。
接下來,若 \(q_1\) 被欽定,那么 \(q_i\) 也已經固定下來,檢查每條邊是否滿足要求以及 \(q_i\) 是否在 \([0,p_i]\) 范圍內,判斷無解。
否則,根據若干組 \(0\leq k_iq_1+c_i\leq p_i\) 的不等式,我們可以解得 \(q_1\) 的取值范圍 \([l,r]\)。我們知道 \(q_i\) 的總和為 \(\sum\limits_{i=1}^{|V|}k_iq_1+c_i\),記 \(K=\sum\limits_{i=1}^{|V|}k_i\),\(C=\sum\limits_{i=1}^{|V|}c_i\),\(P=\sum\limits_{i=1}^{|V|}p_i\),則代價為 \(P-Kq_1C\)。顯然,該式的最小值與最大值在 \(q_1\) 等於邊界值時取到,分 \(K\leq 0\) 和 \(K>0\) 兩種情況討論一下即可。時間復雜度線性。
*P3545 [POI2012]HUR-Warehouse Store
世 界 線 收 束。法一是按 \(b_i\) 從小到大貪心,對 \(a_i\) 做前綴和,那么 \(b_i\) 合法當且僅當 \(a_i\sim a_n\) 都 \(\geq b_i\)。此時我們選擇 \(b_i\) 且令 \(a_i\sim a_n\) 減去 \(b_i\)。線段樹維護區間修改區間最值。
法二就很巧妙了:考慮當前剩余貨物 \(c\),從小到大枚舉每個 \(i\)。若 \(b_i\leq c\) 說明可以暫時選 \(b_i\),\(c\gets c-b_i\)。否則若 \(b_i\) 大於已經選的某個 \(b_j\ (j<i)\),我們可以貪心地去掉 \(j\) 選上 \(i\),\(c\gets c-b_j+b_i\)。就不證了。可以用優先隊列 priority_queue
維護。時間復雜度都是線性對數。
*P3546 [POI2012]PRE-Prefixuffix
好題!不難發現若 \(S,T\) 循環相同則它們可以分別被寫成 \(AB\) 和 \(BA\) 的形式。因此題目相當於:對於 \(S\) 的每個 border 長 \(p\ (2p\leq S)\),求 \(S\) 去掉 \(p\) 前綴和 \(p\) 后綴后最長的不重疊 border 長 \(q\),則 \(\max p+q\) 即答案。
\(p\) 是好求的,但每個 \(S[p+1,n-p]\) 的 border 就不好求了。考慮 \(S\) 所有這樣的子串串 \(S_i=S[i+1,n-i]\),\(S_i\) 的 border 掐頭去尾后變成了 \(S_{i+1}\) 的 border,因此 \(|B_{\max}(S_i)|\leq |B_{\max}(S_{i+1})|+2\)。
根據這一性質,我們從大到小枚舉所有 \(i\ (1\leq i\leq n/2)\),維護長度 \(p\) 表示 \(S_i\) 的最長不重疊 border 長。當 \(i\to i-1\) 時,令 \(p\gets p+2\),然后不斷減小 \(p\) 直到 \(p\) 是 \(S_i\) 的一個不重疊 border 長。勢能分析,\(p\) 的移動距離不超過 \(2n\)。
判斷字符串是否相等使用哈希,自然溢出哈希會被卡。求 \(S\) 的所有 border 直接 KMP 就行。時間復雜度線性。雙 倍 經 驗。
P6612 [POI2012]LIC-Bidding
編號並不是很連續(大霧)。注意到 \(x\) 只有可能是 \(2^a3^b\) 的形式,因此數量級為 \(\log n\)。
將 \(x\) 離散化,直接暴力 DP 每個 \((x,y)\) 是必勝還是必敗態,時間復雜度線性對數。
2013
*P3550 [POI2013]TAK-Taxis
當前位置 \(p < d\) 時,每個出租車會浪費 \(d - p\) 的路程。因此貪心選擇路程大的出租車先打,這樣浪費的路程就更少。調整法可證。
此外需要預留一個路程 \(\geq m - d\) 的出租車,這樣在 \(d\geq p\) 時可以一步直達,不難發現選擇路程最小的符合要求的出租車最優。時間復雜度是排序的線性對數。
*P3551 [POI2013]USU-Take-out
考慮每次刪去一段連續的 \(k\) 白和 \(1\) 黑,最后倒過來輸出正確性顯然。用棧 + 前綴和維護即可。時間復雜度線性。
P3556 [POI2013]MOR-Tales of seafaring
注意到若 \(i, j\) 之間存在長為 \(d\) 的路徑,則必然存在長為 \(d + 2k\ (k\geq 0)\) 的路徑,沿一條邊來回走就可以做到,因此奇偶 bfs 即可。直接開 \(2n\times n\) 的數組沒法接受,把詢問離線下來,對於每個起始位置單獨回答,空間復雜度線性,時間復雜度 \(\mathcal{O}(nm + k)\)。
*P3557 [POI2013]GRA-Tower Defense Game
挺有意思的一道題目。考慮枚舉每個點,如果沒有被覆蓋,那就直接在這個地方建座塔,然后把所有覆蓋到的點刪掉。正確性是因為存在大小小於 \(k\) 的點覆蓋集,因此每個點至少與一個點覆蓋集中的點相連,在每個點建塔都能覆蓋到與所有與該點相連的點覆蓋集中的點所能覆蓋的點,故貪心正確。
同時,一個點最多僅會作為一次與某座塔距離為 \(1\) 的點(因為在此之后所有相鄰點都被打上了標記,自然不會再作為塔),遍歷其所有出邊打標記。故時間復雜度線性。
*P3558 [POI2013]BAJ-Bytecomputer
沒看出來是 DP,直接貪心,枚舉最終的 \(0\) 段 \([l, r]\),符合要求當且僅當 \([1, l - 1]\) 為空或 \(a_i = -1\) 且 \([r + 1, n]\) 為空或 \(a_{r + 1} = 1\),因為 \([1, l - 1]\) 都得是 \(-1\),而 \([r + 1, n]\) 都得是 \(1\)。
設 \(pre_i\) 表示將 \([1, i]\) 操作成全 \(-1\) 的代價,前綴和預處理。\(suf_i\) 表示將 \([i, n]\) 操作成全 \(1\) 的代價,后綴和預處理。運用貪心的思想可知 \(0\) 段 \([l, r]\) 一定是 \(a\) 的極長 \(0\) 段,前面可以再帶一個 \(1\)(即 \(a_l = 0 / 1\) 且 \(a_{l + 1\sim r} = 0\)),此時代價為 \(pre_{l - 1} +suf_{r + 1} + a_l\),因為 \(a_{l - 1} = -1\),需要 \(a_l\) 的代價將 \(a_l\) 變成 \(0\)。此外還要用所有 \(pre_i + suf_{i + 1}\) 更新答案。
P3560 [POI2013]LAN-Colorful Chain
two-pointers 維護答案,時間復雜度線性。
2014
P3572 [POI2014]PTA-Little Bird
由於 \(d_j\leq d_i\) 的貢獻僅有 \(1\),因此將 \(i\) 壓入隊列和隊尾 \(t\) 比較時,若 \(f_i < f_t\) 或 \(f_i = f_t\land d_i\geq d_t\),說明 \(i\) 不劣於 \(t\):當 \(f_i<f_t\) 時,顯然有 \(f_i+[d_i\leq d_{i’}]\leq f_t + [d_t\leq d_{i'}]\)。時間復雜度 \(\mathcal{O}(nq)\)。
2015 (2021.12.8-12.10)
P3582 [POI2015]KIN
考慮增量法,實施維護右端點 \(r-1\to r\) 時每個左端點的貢獻。設 \(p\) 表示 \(f_r\) 在 \(r\) 之前倒數第二次出現位置,\(q\) 表示最后一次出現位置,那么 \(q+1\sim r\) 加上 \(w_{f_r}\),\(p+1\sim q\) 減去 \(w_{f_r}\), 區間修改全局 \(\max\),線段樹維護即可。
*P3583 [POI2015]KWA
打表猜結論題。首先這道題目長得就一臉可以打表的樣子,所以我們先通過 DP 求得一點小數據的 \(w\) 值。
輸出到 \(10^4\),發現一個比較明顯的分割點在 \(9455\) 這個地方:因為 \(9455=S(30)=\sum\limits_{i=1}^{30}i^2\) 所以它是最后一個 \(w\) 值為 \(30\) 的數,顯然若 \(i>9455\) 則 \(w(i)>30\)。這給予我們第一個思想:當 \(i\) 很大的時候,\(j^2\ (j\leq i)\) 的組合能夠生成的數覆蓋了幾乎所有 \(S(i-1)\sim S(i)\) 之間的數,以及當 \(n>S(i)\) 時,必然有 \(w(n)>i\)。
但再觀察表,發現在 \(9455\) 的前面有一些 “超重” 數,它們的 \(w\) 值為 \(31\)。乍一看似乎沒啥規律,不過仔細思考后可以發現,這些超重數 \(p\) 與 \(9455\) 之間的差 \(q\ (q=9455-p)\),應該就是所有 \(w(q)=\infty\) 的 \(q\)。畢竟 \(p\) 應該由 \(1\sim i\) 的平方之和減掉一些數的平方得到,但如果它們的差(\(n-p\))即要減去的數不能由若干個不同的完全平方數之和得到,那么 \(p\) 也不能由 \(S(i)\) 減去一些不同的完全平方數得到,這說明 \(w(p)\) 不得不大於 \(i\)。
接下來我們證明在 \(p\) 足夠大的時候,一定有 \(w(p)=i+1\),其中 \(i\) 為使得 \(S(i)\geq p\) 的最小的 \(i\) 且 \(S(i)-p\) 不能由若干完全平方之和表示:設 \(q=S(i+1)-p\),由於不能被若干完全平方之和表示的數有限(共有 \(31\) 個且最大值為 \(128\)),所以 \(p\to \infty\) 時 \(q\gg 128\),因此 \(w(q)\neq \infty\),這說明 \(p\) 可以由 \(S(i+1)\) 減去若干完全平方數得到,故 \(w(p)=i+1\)。
綜上,我們有如下算法:首先暴力求出 \(n\) 比較小時的 \(w(n)\)(大概到 \(10^3\) 級別就夠了,設范圍為 \([1,x]\)),若給定的 \(n\) 屬於 “比較小”,即 \(n\leq x\),直接輸出答案。否則二分求出最小的 \(i\) 使得 \(S(i)\geq n\),那么第一問的答案即 \(i+[\exist j,\ w(j)=\infty\land n+j=S(i)]\),第二問的答案可以由 \(n\) 較小時的超重數之和,加上從 \(x+1\) 到 \(n\) 之間所有超重數得到。
因為對於固定的 \(j\),所有 \(w(p)=j\) 的 \(p\) 中有 \(31\) 個超重數(可表示為 \(S(j-1)-q\),其中 \(w(q)=\infty\)),所以令 \(l\) 為 \(S(l)\leq x\) 的最大的 \(l\)(注意這個分割點 \(x\) 不應該取到比較靠近形如 \(S(i)-d\) 其中 \(d\) 是一個很小的數的位置,因為這樣會把 \(w(p)=l\) 的超重數 \(p\) 分割成 \(\leq x\) 和 \(>x\) 兩部分,無法直接用 \(31\) 乘以 \(j\) 的個數計算),答案加上 \(31\times (i-1-l)\),再枚舉 \(w(q)=\infty\) 的 \(q\),若 \(S(i)-q\leq n\) 說明 \(S(i)-q\) 這一超重數的貢獻也要算上,答案加 \(1\)。
除去預處理的常數復雜度,時間復雜度為二分求 \(i\) 的 \(\log n\)。代碼預處理到了 \(10^4\),此時 \(l=30\) 所以上式可改寫為 \(31\times (i-31)\)。
**P3584 [POI2015]LAS
第一個想法是若出現相鄰的兩個食物 \((x,y)\) 滿足 \(2a_x<a_y\) 或 \(2a_y<a_x\),說明能夠選擇食物 \(x,y\) 的人一定會選擇 \(a\) 值較大的那一個,因為就算有人和他搶食物他也能吃到熱量較高的那個。
可能出現欽定一個人在 \(x,y\) 之間選擇 \(y\) 后 \(y,z\) 又出現了一個數大於另一個數的兩倍的情況,所以用隊列進行 “松弛”。
松弛完畢后,對於沒有欽定食物的所有人貪心地選擇他相鄰兩個食物中熱量較高的那個即可。若 \(x\) 選了食物 \(x+1\),那么 \(x+1\) 就一定不會選食物 \(x+1\),因為 \(\dfrac{a_{x+1}}{2}\leq a_{x+2}\)。故兩個沒有欽定食物的人不可能選到同一食物,所以每個人的決策互不干擾,貪心正確性得以保證。
為防止出現小數的情況,可以在一開始將所有食物熱量乘以 \(2\)。注意此時判斷 \(2a_x<a_y\) 需要開 long long
。時間復雜度線性。
P3585 [POI2015]PIE
從上到下從左到右找到第一個需要被塗黑的地方,然后用印章從上到下從左到右第一個凸起對應該位置印一遍並實時更新所有需要被塗黑的地方(因為一個位置只能塗一次),需要預先存儲所有凸起位置否則時間復雜度會炸。若有凸起對應的位置超出范圍或不需要被塗黑則無解。時間復雜度 \(\mathcal{O}(Tnm)\)。
*P3586 [POI2015]LOG
和聯考之前考過的某一題基本上完全一樣。每次貪心選最大的 \(c\) 個肯定沒問題,但沒辦法直接模擬。
因為每個數之間順序無關,此時一般通過將序列排序尋找性質:對於最大的元素 \(a_1\),若 \(a_1\geq s\) 說明 \(a_1\) 必定能貢獻 \(s\) 次取數,那么直接令 \(c\gets c-1\) 然后考慮剩下來 \(n-1\) 個數,這是一個子問題。遞歸邊界是出現 \(a_i<s\),這說明 \(a_i\sim a_n\) 都小於 \(s\),此時每個 \(a_i\) 必定可以貢獻滿。現在問題轉化為要求選 \(s\) 次,每次選 \(c\)(這里的 \(c\) 實際上是詢問的 \(c\) 減去 \(\geq s\) 的數的個數)個不同的數,每個數被選擇的次數不超過 \(a_i\) 其中 \(a_i<s\)。
證明:看成一個 \(s\times c\) 的表格,每一行的數互不相同且 \(i\) 的出現次數不超過 \(a_i\),我們有如下方案:對於每個 \(i\) 有 \(a_i\) 次填數,每次選擇最左邊有空位的列的最上面那個位置填入 \(i\) 即可,即填數的軌跡是這樣的:\((1,1)\to(2,1)\to\cdots\to(n,1)\to (1,2)\to(2,2)\to\cdots\to (n,2)\to\cdots\)。因為對於軌跡上任意連續 \(n\) 個格子都有橫坐標互不相同,所以符合條件。
因為對於軌跡上任意連續 \(n\) 個格子都有橫坐標互不相同,所以符合條件。因此,只需判斷是否有 \(\sum\limits_{j=i}^n a_j\geq c\times s\) 即可。具體地,我們求出所有 \(a_i\geq s\) 的 \(i\) 的個數 \(m\),以及所有小於 \(s\) 的數的和 \(v\),若 \(s\times (c-m)\leq v\) 則可行,否則不可行。這可以通過離散化 + 樹狀數組實現。時間復雜度線性對數。
*P3587 [POI2015]POD
類似求子區間個數的題目可考慮使用增量法。將這種思想運用到本題,考慮對於切在 \(i\) 的一刀從 \(i\) 挪到 \(i+1\) 的過程中合法的另一刀的位置 \(p\) 如何變化。
首先,當 \(i=0\) 時,\(p\) 一定滿足對於任意顏色 \(c\) 都有 \(1\sim p\) 要么包含所有顏色為 \(c\) 的珠子,要么不包含任意一個。也就是說對於每一種顏色,將所有出現的珠子看成一個環,那么合法的另一刀位置位於第一刀劈開的相鄰兩個珠子之間。
根據這一性質我們已經有了一個非常直接的做法:線段樹維護區間最小值,數量,以及取到最小值的位置的最小值和最大值(這兩個為了第二問),還需要支持區間修改。對於每個斷點,找到沒有被覆蓋 “不合法線段” 的位置之和,即 \([1,n]\) 等於 \(0\) 的位置個數。由於斷點處一定沒有被任何不合法線段覆蓋,所以就是 \([1,n]\) 取到區間最小值的位置數量 \(-1\)。第二問通過對應區間維護的最小值和最大值計算即可。時間復雜度線性對數,常數非常大。
運用題解區的哈希可以做到線性,而且常數很小。這個哈希維護本質相同區間套路在昨天 2021.12.18 的模擬賽中出現了。
P3588 [POI2015]PUS
裸的線段樹優化建圖板子吧。對於每個區間被選中的數 \(p_1,p_2,\cdots,p_k\),向區間 \([l,p_1-1],[p_1+1,p_2-1],\cdots,[p_k+1,r]\) 連邊表示 \(p_i\) 大於這些區間中的任何數。若干個點向若干個區間兩兩連邊可以建虛點優化 + 線段樹區間連邊。注意只有當指向的節點為葉子結點時有指向的點的值要小於當前點的值,否則只需滿足不大於。時間復雜度線性對數。
*P3589 [POI2015]KUR
求出現次數的題目可轉化為求可能的出現位置數量,本題就運用了這一思想。我們定義小串 \(t\) 在 \(c\) 中的一次出現位置為 \(q\ (q\in [-1,n-m-1])\) 表示 \(\forall i\in[1,m],t_i=c_{q+i}\)。不難發現 \(>n-m\) 的 \(q\) 是不合法的,因為它們超出了范圍。
枚舉每個字符 \(t_i\)。若 \(t_i=\texttt 0\) 說明 \((a(q+i)+b) \bmod n\in [0,p−1]\)。這是一個不等式形式的限制,\(t_i=\texttt 1\) 同理。盡管在這樣一個限制下 \(q\) 的解集可能不連續,但合法的 \(aq\) 范圍一定連續(在 \(\bmod n\) 意義下),因為 \(aq+(ai+b)\bmod n\) 是一段區間,而 \(ai+b\) 是常數。
同時,由於題目保證了 \(a\perp n\),所以一個 \(aq\) 解唯一對應一個 \(q\in [-1,n-2]\) 的解,所以我們只需求出合法的 \(aq\) 個數,但要去掉不合法的 \(q\)。
對於 \(m\) 個限制我們可以得到 \(m\) 個不等式,它的解集是在 \(\bmod n\) 意義下的一段區間,而所有解集的交除去所有不合法的 \(q\ (q\in [n-m,n-2])\) 所得到的 \(aq\) 后集合的大小即為所求。
注意求解集交不能直接對左端點取 \(\max\),對右端點取 \(\min\),因為我們是在 \(\bmod n\) 意義下求交(類似於環上區間求交),所以一個區間對應到 \([0,n-1]\) 上可能會形成兩段區間,這是無法處理的,只能通過離散化 + 差分求覆蓋次數解決。
除掉不合法的 \(aq\):將所有這樣的 \(aq\) 拎出來排個序,在(所有限制差分掉之后)求前綴和(后綴和也行,兩種方法不同點在於如何用一個離散化的值 \(v_i\) 表示區間)的過程中用雙指針掃一遍,表示落在當前離散化的值所表示區間的 \(aq\) 范圍(從而求得數量),就可以在計算答案時去掉這些數的貢獻了。時間復雜度線性對數。
**P3590 [POI2015]TRZ
神仙思維題,暴力能過就離譜,建議去 BZOJ 上提交。
施工 ing ……
P3591 [POI2015]ODW
比較套路的根號分治題目。由於當步長 \(>B\) 時最多走 \(\dfrac n B\) 步,所以我們設置一個閾值 \(B\),表示若步長 \(\leq B\) 則使用預處理的信息,若步長 \(>B\) 則暴力樹上倍增計算。
預處理的信息只需要 \(v_{k,u}\) 表示 \(u\) 每次向上跳 \(k\) 步能到達的所有節點權值之和,即 \(\sum\limits_{v\in \mathrm{ancestor}(u)}a_v[k\mid dep_u-dep_v]\)。可以在 \(\mathcal{O}(nB)\) 的復雜度內求得。
綜上,時間復雜度 \(\mathcal{O}\left(nB+\dfrac{n^2}{B}\log n\right)\),當 \(B\) 取 \(\sqrt{n\log n}\) 時有理論最優復雜度 \(n\sqrt{n\log n}\)。如果用長鏈剖分求樹上 \(k\) 級祖先則可做到嚴格 \(n\sqrt n\)。
由於數據原因,實際表現中取 \(B=20\) 會很快。
*P3592 [POI2015]MYJ
區間 DP 好題。因為 \(c_i\) 具體值不重要,只關心相對大小,所以離散化 \(c_i\)。設 \(f_{l,r,x}\) 表示區間 \([l,r]\) 最小值不小於為 \(x\) 的答案。由於要輸出方案所以記錄 \(v_{l,r,x}\) 表示 \(f_{l,r,x}\) 的區間最小值取了 \(v_{l,r,x}\),以及 \(d_{l,r,x}\) 表示 \(f_{l,r,x}\) 的分割點,這說明 \(f_{l,r,x}\) 由 \(f_{l,d_{l,r,x}-1,v_{l,r,x}}\) 和 \(f_{d_{l,r,x}+1,r,v_{l,r,x}}\) 轉移而來。
轉移枚舉斷點 \(k\),則貢獻為 \(f_{l,r,x}=cx+\max\limits_{k\in [l,r]}f_{l,k-1,x}+f_{k+1,r,x}\),其中 \(c\) 是滿足 \(l\leq a_i\leq k\leq b_i \leq r\) 的 \(i\) 的個數,可以在枚舉 \(l,r,k\) 的時候 \(\mathcal{O}(m)\) 預處理。注意還要和 \(f_{l,r,x+1}\) 取 \(\max\)。時間復雜度 \(\mathcal{O}(n^3m)\)。
P3594 [POI2015]WIL-Wilcze doły
考慮實時維護對於當前 \([l,r]\) 所有連續 \(p\) 個數的和的最大值,前綴和 + 雙指針 + 單調隊列優化即可。\(r\to r+1\) 時往單調隊列加入 \(\sum\limits_{i=r-p+2}^{r+1} a_i\),不滿足條件令 \(l\to l+1\) 時若單調隊列隊首是 \(\sum\limits_{i=l}^{l+p-1}a_i\) 則彈出。時間復雜度線性。
*P3596 [POI2015]MOD
提供一個被卡空間的做法:設 \(d(S)\) 表示點集 \(S\) 的直徑的兩個端點,因為 \(d(S\cup T)\subseteq d(S)\cup d(T)\),而斷掉一條邊之后形成的子樹 dfs 序連續,所以考慮倍增記錄一段連續 dfs 序對應點集的直徑端點。合並兩個點集總共四個直徑端點,只需要對這些點任意兩兩組合的六組點分別求樹上距離,取距離最大的那組即可。
因此我們需要 \(\mathcal{O}(1)\) 求樹上 LCA,考慮 \(\mathcal{O}(n\log n)-\mathcal{O}(1)\) RMQ 求解,時空復雜度即 \(\mathcal{O}(n\log n)\)。但因為我們開了過多倍增數組所以無法通過,只能獲得 \(30\) 分的好成績。
正解是換根 DP。斷掉一條邊 \((u,v)\ (u=fa_v)\) 后 \(v\) 子樹內的直徑可以在最開始一遍 dfs 求出,因此考慮包含根的連通塊的直徑如何得到,設其長度為 \(g_v\)。
若直徑不經過 \(u\),有兩種情況:斷掉 \((u,fa_u)\) 后包含根的連通塊的直徑即 \(g_u\),或 \(u\) 除 \(v\) 以外的所有子節點的子樹直徑最大值。
若直徑經過 \(u\),也有兩種情況:\(u\) 的子樹內最長的兩條以 \(u\) 為一端且不經過 \(v\) 的鏈之和(通俗地說,就是 \(u\) 向下最長的不經過 \(v\) 的兩條鏈),或 \(u\) 向下最長的不經過 \(v\) 的鏈加上經過 \((u,fa_u)\) 這條邊且以 \(u\) 為一端的最長鏈(即 \(u\) 向上的最長鏈)。
綜合一下,我們需要預處理出 \(u\) 向下最長的三條鏈 ,\(u\) 的所有兒子的子樹最長的兩個直徑,並且在換根 DP 的過程中同時求出 \(u\) 向上的最長鏈(可以由 \((u,fa_u)\) 這條邊與 \(fa_u\) 向上的最長鏈或者 \(fa_u\) 向下不經過 \(u\) 的最長鏈拼起來得到)。
求出斷掉每一條邊后形成的兩個連通塊的直徑 \((u,v)\) 和 \((x,y)\) 后,顯然最長直徑為 \(u/v\) 和 \(x/y\) 相連,最短直徑為 \((u,v)\) 中點與 \((x,y)\) 中點相連,從而求得新的直徑的最大值和最小值,更新答案。
記錄最大值和最小值分別由斷掉哪一條邊得到,最后再斷掉這條邊,暴力地對於兩個連通塊,分別對最大值求直徑兩端,對最小值求直徑中點。時間復雜度線性,寫起來比較麻煩。
P3597 [POI2015]WYC
非常顯然的矩陣快速冪,由於邊權只有 \(3\) 所以拆點,存儲 \(f_{i,j},f_{i,j+1}\) 和 \(f_{i,j+2}\) 表示以 \(i\) 結尾的長度為 \(j,j+1,j+2\) 的路徑數量。最后再計一個 \(sum\) 表示路徑總數,得到轉移矩陣 \(B\)。預處理出 \(B^1,B^2,\cdots,B^{61}\),然后倍增求解即可。時間復雜度 \(\mathcal{O}(n^3\log k)\),有 \(27\) 倍常數。注意矩陣每個數在任何時候都要對 \(k\) 取 \(\min\)。
2016
*P5970 [POI2016]Nim z utrudnieniem
根據取石子游戲的經典理論,我們需要選出 \(k\) 堆石子,使得 \(k \neq 0\),\(d\mid k\) 且這 \(k\) 堆石子的異或和等於 \(\bigoplus a_i\)。
考慮設計 \(f_{i, j, k}\) 表示前 \(i\) 堆石子中選出 \(\bmod d = k\) 堆,異或和為 \(j\) 的方案數,直接做的復雜度是 \(\mathcal{O}(2 ^ {20}dn)\),因為不大於 \(10 ^ 6\) 的數最大可能異或出 \(2 ^{20} - 1\),無法接受。但注意到 \(\sum a_i\) 有限制,說明有很多堆石子,石子數都很少。因為石子順序不影響答案,如果我們按從小到大的順序排列石子,那么前 \(i\) 堆石子能夠異或得到的所有數均不超過不小於 \(a_i\) 的最小的 \(2\) 的冪 \(2 ^ r < 2a_i\),這樣一來我們只需枚舉到 \(2 ^ r\) 而非 \(2 ^ {20}\)。總復雜度均攤下來就是 \(\sum a_i\) 而非 \(a_i \times n\)。故可以通過,時間復雜度 \(\mathcal{O}(md)\),空間復雜度使用滾動數組優化后為 \(\mathcal{O}(2 ^ {20} d)\)。
2017
P5968 [POI2017]Reprezentacje ró?nicowe
注意到當 \(n > 56\) 時,\(a_n > 10 ^ 9\),所以接下來只有 \(a_{2k} - a_{2k - 1}\) 對答案有貢獻,且依次是前 \(56\) 個數兩兩作差組合不出來的數從小到大排列的結果。預處理前 \(56\) 項兩兩差,每次詢問二分即可。時間復雜度 \(\mathcal{O}(n\log(\log^2 x))\)。
2018
*P5952 [POI2018]水箱
還算有意思的一道題目。對整個網格圖求最小生成樹。合並 \(x, y\) 的方案數即 \((f_x + w - w_x)(f_y + w - w_y)\)。其中 \(f_x\) 表示該連通塊當前的方案數,\(w\) 表示當前高度,\(w_x\) 表示該連通塊當前高度,初始值為 \(-1\)。合並時實時更新 \(f\) 和 \(w\)。時間復雜度線性對數。
2019
P6659 [POI 2019] Najmniejsza wspólna wielokrotność
\(b - a \leq 2\) 容易判斷,對於 \(b - a \geq 3\) 的,發現 \(a\leq 5\times 10 ^ 4\),所以預處理所有左端點 \(\leq 5\times 10 ^ 4\) 的區間的 \(\mathrm {lcm}\) 的答案,用 map
存儲。時間復雜度線性對數。
P6661 [POI 2019] Pomniejszenie
陰間模擬題。考慮求出使得 \(A, B\) 不同的第一個位置 \(p\),有如下限制:
- 需要修改的位置數量不能超過 \(k\)。
- 沒有考慮到的位置數量不能小於還需要修改的位數。
具體地,對於每一位 \(i\),求出 \(s\) 表示在第 \(i\) 位之前有多少 \(A\neq B\) 的位置。\(i\) 合法的必要條件是 \(B_i \neq 0\),先判掉。由於上述限制要求修改位置數量既不能太小,也不能太大,所以需要考慮當前位是否修改:
- 若 \(A_i < B_i\),說明可以不修改。此時若 \(s \leq k\) 且 \(n - i \geq k - s\) 則 \(i\) 合法。
- 若 \(B_i > 1\) 或 \(A_i > 0\),說明可以 強制 修改(因為當 \(A_i = 0, B_i = 1\) 時不能修改)。此時若 \(s + 1\leq k\) 且 \(n - i \geq k - s - 1\) 則合法。
若找不到合法的 \(p\) 則無解。輸出答案的過程時刻維護 \(k\) 表示還需要修改的位數:
- 若當前位 \(i\) 小於 \(p\),輸出 \(B_i\)。
- 若當前位 \(i\) 等於 \(p\),此時當 \(n - i - 1 = k\) 且 \(A_i + 1 = B_i\) 時輸出 \(B_i - 2\),否則輸出 \(B_i - 1\),前者因為這一位必須修改(否則將導致剩余位數小於要修改位數,不合法)。
- 若當前位 \(i\) 大於 \(p\),此時當 \(n - i - 1 = k\) 且 \(A_i = 9\) 時輸出 \(8\),否則輸出 \(9\)。
- 注意點:若輸出的數碼與 \(A_i\) 不同,則令 \(k\) 自減 \(1\)。
- 注意點:任何時刻若 \(k = 0\),則輸出 \(A_i\)。
時間復雜度線性。