新建這篇博客的時候發現自己在NOI之后只發過兩三篇博客,而且都基本上沒什么實質性內容。
果然是巨大混混人啊。
本文承接上篇(不過好像爛尾了),旨在記錄一些有趣(?)的內容。
12.23
北大集訓過去好些天了。
對退役這件事情幾乎無感,IOI也並非自己所堅信的道路。
但這也只是逃避的說辭罷了。
不過有一說一,退役二字本身還是很讓人沮喪的。至少不能夠把這種挫敗感帶到機房傳染給學弟們。
以后還是會做點題什么的,畢竟在近一兩年里總還是會被打上,或者說需要依賴於這引以為傲的OIer標簽的。
當然也會有些別的計划,在此就不多提及了。
下午補了USACO的題。T3那個數數題在北大集訓前鼠就跟我講過但好像當時......根本沒有腦子?
「USACO 2019.12 Platinum」Greedy Pie Eaters
首先可以認為每個區間都對應一頭牛(若不存在可以認為牛的體重為\(0\)),記\(A_{l,r}\)表示區間\([l,r]\)對應的牛的體重,顯然最終會選出恰好\(n\)頭牛,每頭牛吃恰好一個派。
考慮區間dp。枚舉區間\([l,r]\),並枚舉區間內最后一個被吃掉的派\(k\)。
\(f_{l,r}=\max_{l \le k \le r}\{f_{l,k-1}+f_{k+1,r}+g_{l,k,r}\}\),其中\(g_{l,k,r}=\max_{l \le x \le k \le y \le r}A_{x,y}\)。
\(g\)可以和\(f\)一起算,即\(g_{l,k,r}=\max\{g_{l+1,k,r},g_{l,k,r-1},A_{l,r}\}\),可以把其中一維用滾動數組優化掉。
「USACO 2019.12 Platinum」Bessie's Snow Cow
直接用std::set維護每種顏色的子樹並,再安排個樹狀數組支持區間加區間求和就完事了!!1
「USACO 2019.12 Platinum」Tree Depth
一件(眾所周知的)事情是設\(f_{n,k}\)表示逆序對數為\(k\)的\(n\)階排列的數量,那么其生成函數\(F_n(x)=\sum_{k\ge 0}f_{n,k}x^k\)滿足
大致含義是考慮排列的生成方式,每次在一個\(i\)階排列的末尾添加一個新的數字,根據新添加的數字與原數的大小關系可以得到逆序對數的增量。
另一件(眾所周知的)事情是在考慮排列中某個位置在對應的笛卡爾樹上的期望深度時,常常根據期望的線性性,轉化成考慮其余每個位置在笛卡爾樹上作為這個位置的祖先的概率。具體的,一個\(n\)階排列中,\(i\)作為\(j\)在笛卡爾樹上的祖先的充要條件為:\(p_i\)是區間\([i,j]\)(或區間\([j,i]\))中的最小值,而這個概率顯然是\(\frac{1}{|i-j|+1}\)。
回到原問題。考慮枚舉\(i,j\),計算有多少逆序對數為\(k\)的排列滿足\(i\)是\(j\)在笛卡爾樹上的祖先。相當於是在插入\(i\)位置時強制其為當前最小,也即對於上述的生成函數\(F_n(x)\),把\(\prod\)中\(\sum_{k=0}^{|i-j|}x^k\)項改為\(1\)或者\(x^{|i-j|}\)(根據\(i,j\)的大小關系,會發現當\(i<j\)時插入\(i\)不會貢獻逆序對,\(i>j\)會貢獻恰好\(i-j\)個逆序對)。
只需要計算出\(F_n(x)\),然后每次除掉一個\(\frac{1-x^i}{1-x}\)即可。
晚上口胡了下PKUWC。jlsnb!
12.24
今日不更。
12.25
今日不更。
12.26
zsy啊zsy,你不能再這樣頹廢下去了呀。
更一些退役后的寫水題記錄。
「PA 2019」A + B
「PA 2019」Muzyka pop
先假想有一棵包含了\([0,m]\)所有數的二進制\(\text{Trie}\),那么就可以實現一個很簡單的動態規划:記\(f_{x,l,r}\)表示把\(b_l,...,b_r\)選在\(\text{Trie}\)樹上\(x\)節點的子樹里的最優解,轉移時枚舉\(k \in [l-1,r]\)表示把\(b_l...b_k\)放到\(x\)的左兒子,剩下的放到右兒子,那么此處便產生貢獻\(a_{k+1}+...+a_r\)。
可以發現這棵二進制\(\text{Trie}\)除了表示\(m\)的葉子到根的那一條鏈外每個點的子樹都是完全二叉樹,因此在動態規划中只需要記錄\(x\)的深度以及\(x\)在不在\(m\)到根的鏈上即可,時間復雜度\(O(n^3\log m)\)。
「PA 2019」Desant
朴素狀態壓縮動態規划的復雜度是\(O(n2^n)\),需要記錄每一個數字是否被選取。但直觀來想,隨着選取的數字越來越多,我們不再那么關心每個數字是否被選取,而只關心某些值域區間里被選取了多少數字。
對於每個\(i \in [1,n]\),將\(a_i,a_{i+1},...,a_n\)從小到大排序,設排序后為\(b_1,b_2,...b_{n-i+1}\),我們只關心每個\((b_j,b_{j+1})\)區間內被選了多少個數字(\(j \in[0,n-i+1]\),定義\(b_0=0,b_{n-i+2}=n+1\))。因此,在考慮完前\(i-1\)個數的選取后,我們只需要在狀態中記錄前述的每個區間被選取了多少數字即可,這個狀態總量顯然為\(\prod_{j=0}^{n-i+1}(b_{j+1}-b_j)\)。
考慮一下總狀態數。可以發現狀態數的總量不超過\(\sum_{k=1}^n\max\{\prod_{i=1}^ka_i|a_i \in \mathbb{N}^*, \sum_{i=1}^ka_i = n+1\}\)。眾所周知取盡量多的\(3\)是最優的,因此在\(k=\frac{n+1}{3}\)時的最大值為\(3^{\frac{n+1}{3}}\)。所有\(k\)的最大值之和不太會分析,但顯然不超過\(O(n3^{\frac{n+1}{3}})\)。鑒於狀態轉移是\(O(1)\)的,復雜度還算可以接受。
「PA 2019」Trzy kule
先小學生容斥一下變成求一個/兩個/三個串同時滿足限制。
一個串滿足限制答案就是\(\sum_{i=1}^r\binom{n}{i}\)。
兩個串滿足限制,可以把第一個串變為全\(0\),記第二個串有\(A\)個\(0\),\(B\)個\(1\),答案是$$\sum_{\substack{a+b\le r_1\a+B-b\le r_2}}\binom{A}{a}\binom{B}{b}$$
可以\(O(n)\)統計答案。
三個串滿足限制,同理把第一個串變為全\(0\),記后兩個串\(00/01/10/11\)組合各有\(A,B,C,D\)個,答案是$$\sum_{\substack{a+b+c+d\le r_1\a+b+C-c+D-d\le r_2\a+B-b+c+D-d \le r_3}}\binom{A}{a}\binom{B}{b}\binom{C}{c}\binom{D}{d}$$
枚舉\(c,d\)后發現\(a,b\)有形如\(a+b \le x, a+B-b \le y\)的限制,暴力二維前綴和即可,復雜度\(O(n^2)\)。
update:好像直接\(2^n\)減去不合法(全部超過)就行了,我是個麻瓜。
12.27
今日不更。
12.28
今日不更。
1.6
我覺得日更這件事情可能不太適合我。興許可以嘗試一下周更?
「BalticOI 2019 Day2」奧運會
gzy大神教我做的題。
首先有一種想法是直接枚舉每場比賽所有參賽者的最高得分,並計算方案數,然后拿這個方案數與給出的那個\(C\)比較。但這樣的復雜度可能是錯的(至少我不能證明它是對的),因為方案數可能為\(0\),因而無法保證遍歷到的狀態不會超過\(C\)種。
一件奇怪的事情是考慮對於任何一種\(k\)個參賽選手的集合,求一個這\(k\)個選手的排序。可以采用的一種策略是:把第一場比賽得分最高的排在第一位,剩下的人中第二場比賽得分最高的排在第二位,以此類推。
考慮怎么求最優解。一種可行的策略是,先選第一場比賽得分最高的,再在剩下的人中選第二場比賽得分最高的,以此類推。顯然這個貪心選取的順序是符合上述排序的。求出最優解后,不難把剩下的所有方案根據與當前方案的\(lcp\)划分成\(k\)類,每一類都相當於固定了方案的一個前綴,且要求這個前綴的下一位不能是某個選手。而根據前面講的那個排序,會發現一個長度為\(j\)的前綴一定會確定前\(j\)場比賽的最高得分,也就是說限制一個固定前綴的下一位不能填原本的最大值等價於限制了這個原本的最大值再也不能出現。因此就可以用一個bitset
維護尚可以出現在方案中的選手。
因此,搜索的狀態需要記錄如下信息:一個被固定的前綴,尚可以選的集合,以及權值。狀態的權值應被定義為這個狀態能給出的權值最大的方案的權值,計算出這個權值可以使用上述的貪心,緊接着便可以再根據剩余與當前方案的\(lcp\)划分成不超過\(k\)個子狀態。
復雜度大概是\(O(nk^2C)\)。
「POI2019 R1」Przedszkole
激 情 三 合 一
\(n \le 15\)。觀察到答案是關於\(k\)的一個\(n\)次多項式,因此可以直接算出\(k=0,1...n\)的答案后插值。計算一個\(k\)的答案相當於是做獨立集的子集卷積的\(k\)次方,這個可以很輕易地在\(O(2^nn^3)\)時間復雜度內計算出來。
\(m \le 24\)。直接暴力容斥每條邊兩端點是否強制相同,用並查集維護。復雜度\(O(2^m)\),可能還帶個並查集的復雜度啥的。
每個點度數為\(2\)。那么圖就是若干個環,而一個長度為\(l\)的環的色數多項式是\((x-1)^l+(-1)^l(x-1)\),然后不同的環長種數顯然是\(O(\sqrt n)\)的,把環長相同的合並在一起算,復雜度為\(O(q\sqrt n)\)。
1.14
周更\((\times)\)
半月更\((\times)\)
隨緣更\((\surd)\)
Codeforces 736D. Permutations
給定一張兩側各\(n\)個點,共\(m\)條邊的二分圖,保證其完美匹配個數為奇數。對於二分圖的每一條邊,詢問將這條邊刪去后,剩下的二分圖的完美匹配數是否仍為奇數。
\(1 \le n \le 2000, n \le m \le \min(n^2, 5\times 10^5).\)
記\(a_{i,j}\)表示二分圖中是否存在一條從\(i\)連向\(j'\)的邊(存在為\(1\)不存在為\(0\)),那么二分圖完美匹配數為奇數等價於\(\sum_p\prod_{i=1}^na_{i,p_i} \equiv 1 \mod 2\)。由於\(-1 \equiv 1 \mod 2\),所以也等價於\(\det(A) \equiv 1 \mod 2\)。
再考慮刪除一條邊后的完美匹配數怎么計算。容斥,考慮計算強制這條邊在完美匹配中的匹配數,會發現這恰好是\(a_{i,j}\)的余子式\(M_{i,j}\),而我們只關心\(M_{i,j}\)的奇偶性。同樣因為\(-1 \equiv 1 \mod 2\),我們只需要計算\(a_{i,j}\)的代數余子式\(A_{i,j}=(-1)^{i+j}M_{i,j}\)。
求代數余子式只需要求出\(A\)的伴隨矩陣\(A^*\),而由於\(AA^*=A^*A=\det(A)I\),因而\(A^*=\frac{\det(A)I}{A}\),矩陣求逆即可。由於運算均是為\(\mathbb{F}_2\)下進行的,可以壓位優化,最終復雜度為\(O(\frac{n^3}{\omega})\)。
Codeforces 891E. Lust
給定\(n\)個數\(a_1,a_2,...,a_n\)和一個初值為\(0\)的計數器\(cnt\),執行以下操作\(k\)次:
在\(1...n\)中等概率隨機選擇一個數\(x\),令\(cnt\)加上\(\prod_{i \neq x}a_i\),然后把\(a_x\)減\(1\)。
求\(k\)次操作后計數器\(cnt\)的值的期望模\(10^9+7\)。
\(1 \le n \le 5000, 1 \le k \le 10^9.\)
觀察發現每次令計數器加上的值實際上是\(\prod_ia_i-\prod_ia_i'\)。
因此\(k\)次操作后計數器的值至於每個\(x\)被減了多少次有關,與減的順序無關。也即,設\(a_i\)最終被減了\(b_i\)次(\(\sum_i b_i = k\)),那么計數器的值即為\(\prod_ia_i-\prod_i(a_i-b_i)\)。前者是常數,只考慮計算后者。
設指數型生成函數\(F_a(x)=\sum_{i \ge 0}\frac{a-i}{i!}x^i\),那么答案就是\(\frac{k!}{n^k}[x^k]\prod_iF_{a_i}(x)\)。
不難發現\(F_a(x)=e^x(a-x)\),因此答案可以寫成\(\frac{k!}{n^k}[x^k]e^{nx}\prod_i(a_i-x)\)。
因此只需要\(O(n^2)\)求出\(A(x)=\prod_i(a_i-x)=\sum_{i=0}^nc_ix^i\),那么答案就是\(\sum_{i=0}^n\frac{k^{\underline{i}}}{n^i}c_i\)。
1.16
「PA 2019」Podatki drogowe
把權值看做一個\(n\)進制數,由於樹邊只有\(n-1\)條,因此顯然不會進位。對一條路徑開桶記錄權值為\(n^i\)的邊出現了多少次,那么比較兩條路徑的權值大小等價於反着比較兩個桶的字典序大小。
對樹進行點分治,使用可持久化線段樹+哈希的方式維護桶(具體的,對桶的每個位置隨機一個權值,線段樹維護桶的對應區間內的權值和,比較兩棵線段樹時根據右子樹的權值和判斷兩個桶的\(lcp\)是否大於\(mid\)),這樣可以實現\(O(\log n)\)地比較兩條路徑的字典序大小。
考慮如何求第\(k\)大。理想的做法是二分:點分后會將會得到\(O(n\log n)\)棵線段樹,它們會被分為\(O(n)\)個組,每個組里的線段樹兩兩組成一條完整路徑,貢獻還需乘上一個\(\pm 1\)的容斥系數,表示在點分過程中是否被強制選自重心的同一棵子樹。預先對每一組內的線段樹進行排序(使用上述\(O(\log n)\)的比較),對於一條確定的路徑\((u,v)\),可以使用two-points在\(O(m\log n)\)的時間復雜度內求出一個大小為\(m\)的組內有多少條路徑\(\preceq(u,v)\)。因而,若能夠實現快速找出二分中\(mid\)對應的路徑,可以在\(O(n\log^2n)\)的時間復雜度內對一個給定的\(k\)求出答案。
然而現實的問題是無法找出二分中\(mid\)對應的路徑。可以采取隨機的方式:答案一定是在\(O(n\log n)\)棵線段樹中選出兩棵組合而成,維護兩條路徑\((u_l,v_l)\)與\((u_r,v_r)\),每次隨機找出一條路徑\((u_{mid},v_{mid})\)滿足\((u_l,v_l)\preceq(u_{mid},v_{mid})\preceq(u_r,v_r)\)(這個過程與前述的two-points部分幾乎完全一致)並計算有多少條路徑\(\preceq(u_{mid},v_{mid})\)。可以證明隨機次數為\(O(\log n)\)。
值得注意的是,點分后得到的\(O(n\log n)\)棵線段樹需要去重,在隨機若干次后滿足\((u_l,v_l)\preceq(u_{mid},v_{mid})\preceq(u_r,v_r)\)的\((u_{mid},v_{mid})\)數量較少時,需要暴力拿出所有\((u_{mid},v_{mid})\)后排序並二分。否則會被某些特殊數據(比如說邊權全相等的菊花)卡掉。
更多細節可以參考代碼。
1.25
又咕咕咕好幾天了(捂臉)
今天是庚子鼠年的第一天,祝大家新年快樂啦!新的一年要繼續努力喲,加油干奧利給!
近來疫情形勢嚴峻,希望看到這篇文章的你一定要出門戴口罩,記得勤洗手,勤開窗通風,少去人流密集的場所,宅在家里悶聲大發財才是墜吼滴!

figure1. 戴上了口罩的有馬君
1.26
補了USACO的題。
「USACO 2020.1 Platinum」Cave Paintings
同行且四連通的格子的狀態必然是相同的,可以縮成一個點。
對於關系“若\(x\)是水則\(y\)必須是水”連邊\(x \to y\),會發現連成了一片有向森林,因此直接樹型\(dp\)就好了。
具體地,記\(f_x\)表示\(x\)子樹內的方案數,則\(f_x = 1 + \prod f_y\)(\(y\)是\(x\)的兒子)。
代碼實現中可以不顯式地把樹建出,而是使用並查集來維護樹結構。
「USACO 2020.1 Platinum」Non-Decreasing Subsequences
先考慮怎么計算\([1,n]\)的答案。考慮動態規划,記\(f_{i,j}\)表示考慮了前\(i\)個位置,不下降子序列的末尾元素為\(j\)的方案數。對於轉移,有\(f_{i+1,a_{i+1}}=\sum_{j=1}^{a_{i+1}-1}f_{i,j}+2f_{i,a_{i+1}},f_{i+1,j}=f_{i,j}(j \neq a_{i+1})\)。
不難發現上述動態規划可以寫成矩陣的形式。記
(其中那個\(2\)在第\(x\)行\(x\)列)
有\(F_{i+1}=F_iT_{a_{i+1}}\)。因此詢問\([1,n]\)的答案為
現在考慮對於一般的詢問\([l,r]\)求答案。求出\(T_x\)的逆矩陣\(T_x^{-1}\),發現它長這樣
因此,可以考慮預處理
於是一組詢問\([l,r]\)的答案就是\(y_{l-1}x_r\)。
由於矩陣特殊,右乘\(T_x\)或左乘\(T_x^{-1}\)均可以在\(O(k^2)\)的時間復雜度內完成,因此最終的時間復雜度為\(O(nk^2+qk)\)。
「USACO 2020.1 Platinum」Falling Portals
一個(比較顯然)的結論是任意兩點間存在一條經過不超過一個中轉點的最短路,因此暴力做法就只需要枚舉這個中轉點是哪個點就好了。
先考慮\(a_{q_i}<a_i\)的情況。會發現中轉點\(x\)必然滿足\(x\ge \max(i,q_i)\)且\(a_x \ge a_i\),而選定了\(x\)后答案是\(\frac{a_x-a_{q_i}}{x-q_i}\)。可以證明使答案取最小值的\(x\)一定在下凸殼上,因此按照\(a_i\)從大到小枚舉\(i\),維護所有滿足\(j \ge i, a_j \ge a_i\)的點\((j,a_j)\)的下凸殼,對於查詢就只需要在下凸殼上二分找到使目標函數取到最小的位置即可。
對於\(a_{q_i}> a_i\)的情況,只需要相對應地按\(a_i\)從小到大枚舉\(i\),維護\(\{(j,a_j)|j \le i, a_j \le a_i\}\)的上凸殼,查詢同樣二分即可。
2.15
本來打算等到下次出門再更博的,但是發現貌似遙遙無期?
更一點JOI 2020 Final的題。
「JOI 2020 Final」只不過是長的領帶
顯然匹配方式是排序后對應匹配,只需要說明當存在交叉匹配時交換兩者一定不會變劣即可。
將\(a_i\)和\(b_i\)分別排序,那么\(b_i\)將可能匹配\(a_i\)或者\(a_{i+1}\)。不難寫出當選擇\(a_k\)刪除時,答案為\(\max\{0,\max_{j<k}\{a_j-b_j\},\max_{j>k}\{a_j-b_{j-1}\}\}\),維護\(a_j-b_j\)的前綴最大值以及\(a_j-b_{j-1}\)的后綴最大值即可。
「JOI 2020 Final」JJOOII 2
問題等價於選出一個滿足條件的子序列,最小化首尾距離。那么確定了首位之后就可以貪心往后選了。
「JOI 2020 Final」集郵比賽 3
顯然任意時刻已訪問的范圍是一個包含起點的連續區間,由於包含起點,那么記錄這個區間就只需要記錄從原點出發向兩側延伸的長度即可。
記\(f_{i,j,k,0/1}\)表示目前已經考慮過前\(i\)個以及后\(j\)個\((n-j+1...n)\)目標點,目前答案為\(k\),且當前位置在第\(i\)個\(/\)第\(n-j+1\)個目標點上的最早時間。轉移只需要考慮下一步是去\(i+1\)還是去\(n-j\)即可。
「JOI 2020 Final」奧運公交
建出四棵(從\(1\)號點出發、到達\(1\)號點、從\(n\)號點出發、到達\(n\)號點)最短路樹。
若翻轉的邊不再任意一棵最短路樹上,考慮翻轉后的最短路,顯然要么是原最短路,要么必經過翻轉的邊,除了翻轉的邊之外剩余部分一定是沿着最短路樹走,因此可以\(O(1)\)計算出新的最短路。
若翻轉的邊在某一棵最短路樹上,考慮到這樣的邊只有\(O(n)\)條,暴力即可。
由於一次計算最短路的時間復雜度是\(O(n^2+m)\),因此該算法的總時間復雜度為\(O(n^3+nm)\)。
「JOI 2020 Final」火災
用\(a \to b\)表示某個區域的火勢上一時刻為\(a\)而這一時刻為\(b\),那么在整個過程中,本質不同的\(a \to b\)只有不超過\(n\)種,這是因為一個數只會被前面第一個比它大的數給覆蓋掉。
對於一組詢問\(t,l,r\),令答案初值為\(\sum_{i=l}^rS_i\),接下來只需要統計變化的總量,也即,只需要統計所有\(a \to b\)帶來的\(b-a\)之和。
求出\(L_i=\max\{j|j<i,S_j>S_i\},R_i=\min\{j|j>i,S_j>S_i\}\)。
可以發現上述的所有\(a \to b\)其實都是\(S_i \to S_{L_i}\)的形式。
考慮\(S_i \to S_{L_i}\)會在哪些時刻哪些位置發生,會對哪些詢問的答案產生影響。
結論是,對於\(\forall j \in [i,R_i)\),上述過程會在第\(j-L_i\)時刻發生,會使得滿足\(p \in [i,R_i), t \ge p-L_i\)的\(S_p(t)\)的值加上\(S_{L_i}-S_i\)。
如果把\(S_p(t)\)放在二維平面上,不難發現受到影響的區域是一個直角梯形。至此,問題轉化為給出二維平面上的若干直角梯形進行范圍加法,求某一行的區間和(前綴和)。
首先可以把直角梯形差分成兩個三角形,我們用\((\alpha,\beta,\gamma)\)表示一個\(\{S_p(t)+=\gamma|p \ge \alpha, t \ge p - \beta\}\)的修改三角形,上述的直角梯形差分后得到兩個三角形\((i,L_i,S_{L_i}-S_i)\)以及\((R_i,L_i,S_i-S_{L_i})\)。
對於三角形\((\alpha,\beta,\gamma)\),考慮它對於\(t \ge \alpha\)的詢問的影響(在這里,需要對於修改三角形以及詢問按照\(\alpha/t\)排序)。實際上,對於詢問\((t,x)\)的貢獻為\(\gamma(\min(x,t+\beta)-\min(x,\alpha+\beta-1))\)(這里也可以看做是對於三角形左邊界的一個差分)。
考慮怎么把這樣的問題轉化到我們熟練掌握的數據結構問題上。考慮一個簡單的問題:前綴加法,前綴求和。假設一共有\(m\)組\((a_i,b_i)\)表示要將前綴\(a_i\)全部加上\(b_i\),此時若詢問\(c_i\)的前綴和,得到的答案會是\(\sum_ib_i\min(a_i,c_i)\)。
應用到本題,把\(\min(x,t+\beta)\)寫成\(t+\min(x-t,\beta)\),會發現兩者均是上述的形式,因此使用支持前綴加法前綴求和的數據結構維護即可。多出來的\(+t\)大可不必考慮,因為在做前綴相減的時候會被恰好抵消。
3.1
到三月了呢。
「USACO 2020.2 Platinum」Delegation
二分答案\(K\)。對於一個有\(x\)個兒子的節點\(u\),它需要合並產生至少\(\lfloor\frac x2\rfloor\)條完整的路徑,並可能留下半條路徑繼續延伸向\(u\)的父親(注意當\(x\)為偶數時也可能存在向上延伸的路徑)。在保證合法的前提下,向上延伸的路徑應該盡量長,因此可以將\(x\)個兒子的路徑長度排序后,二分求出最長的可向上延伸的路徑(保證其余路徑可以實現合法匹配即可)。根節點不存在可向上延伸的路徑,可能需要一些特判。
總時間復雜度\(O(n\log^2n)\)。
「USACO 2020.2 Platinum」Equilateral Triangles
把坐標系旋轉\(\frac{\pi}{4}\),曼哈頓距離就變成了切比雪夫距離,點\((x_1,y_1)\)與\((x_2,y_2)\)的距離為\(\max\{|x_1-x_2|,|y_1,y_2|\}\)。
簡單討論后可以發現定義在切比雪夫距離下的等邊三角形存在兩個頂點橫坐標相同或縱坐標相同。
枚舉橫坐標相同的兩點\(P(a,b),Q(a,c)(b<c)\),可與之構成切比雪夫距離等邊三角形的第三點坐標集合為\(\{(x,y)|x=a \pm (c-b),b \le y\le c\}\)。
兩點縱坐標相同的情況類似。為避免重復統計,需要強制不存在兩點橫坐標不同,也即枚舉了兩點\(P(b,a),Q(c,a)(b<c)\)后,統計的集合為\(\{(x,y)|b<x<c,y=a\pm (c-b)\}\)。
預處理每個橫縱坐標頂點數的前綴和即可。復雜度\(O(n^3)\)。
「USACO 2020.2 Platinum」Help Yourself
眾所周知\(n^k=k![x^k]e^{nx}\)。
我們可以認為,若一種方案的聯通塊個數為\(n\),那么其生成函數就是\(e^{nx}\)。
對於給出的區間按左端點升序排序依次加入,記\(dp[i]\)表示以\(i\)作為當前最右端點的區間集合的對應的生成函數之和。考慮新加入一個區間\([l,r]\)時,\(dp\)數組的變化情況。
- 若\(i<l\),那么在\(dp[i]\)后面接上新區間\([l,r]\)會使得聯通塊數增加\(1\),因此轉移可以寫成\(dp[r] \gets (\sum_{i<l}dp[i])e^x\);
- 若\(i \in [l,r]\),那么聯通塊數不變,而右端點會變為\(r\),即\(dp[r] \gets (\sum_{l \le i \le r}dp[i])\);
- 若\(i>r\),加入\([l,r]\)后完全沒有影響(區間按照左端點順序加入,\(i>r\)說明此前存在一個滿足\(l'<l,r'>r\)的區間\([l',r']\),因此\([l,r]\)被完全覆蓋了),直接令\(dp[i] \gets dp[i] \times 2 (i>r)\)即可。
使用線段樹實現上述操作,由於一次冪級數乘法的時間復雜度為\(O(k^2)\),因此算法的總時間復雜度為\(O(nk(k+\log n))\)。