A. 施工
又是利用了一些結論的題,因為想不到結論,經常做不出這種題。
枚舉兩個不變的邊界,那么中間的建築必定被提高成相同的小於等於邊界的高度。
於是設$f_i$表示考慮前i個建築,並且第i個建築高度不變的最優答案。
設對於轉移(i,j),中間建築的最優高度為t,可以寫出dp轉移方程。
拆開式子,可以得到一個二次函數。
直接求二次函數最值,可以做到$O(n^2)$。
接着發現很多的轉移是無效的,因為轉移(i,j)要滿足:
任取$i<k<j$,$h(k)<=h(i)$,$h(k)<=h(j)$。
可以維護一個由棧頂到棧底單調遞增的單調棧,以維護轉移的位置。
需要學習的是特殊的打法,用棧頂表示(i,j)范圍內最大的元素,而棧頂-1表示決策點。
B. 蔬菜
正解還是用到了分塊的思想:
1.對於出現次數很多的蔬菜,直接用前綴和累計答案。
2.對於出現次數較少的蔬菜,考慮將平方的含義轉化為點對。
將一棵蔬菜定義為點$(x,y)$,那么任意相同的兩棵蔬菜(可以是同一個棵)可以表示為點對$(x_1,x_2,y_1,y_2)$。
設詢問為$(x,y)(X,Y)$,即統計有多少個點對滿足:
限制(1):$x<=x_1<=X$
限制(2):$x<=x_2<=X$
限制(3):$y<=y_1<=Y$
限制(4):$y<=y_2<=Y$
四維偏序問題,可以暴力四維前綴和容斥。
然而空間復雜度$O(n^4)$,開不下。
考慮離線詢問,並且將每個詢問對於限制(1)拆為兩個,即$ans_X-ans_{x-1}$。
將所有點對按$x_1$排序,所有詢問按拆成的第一維限制排序。
那么對於每個詢問,單調指針不斷添加點對到三維數狀數組里,
添加完后大力三維容斥統計答案就可以了。
設蔬菜由出現次數決定使用哪種算法統計的分界值為k,
那么本題的復雜度為$O(n^2*\frac{n^2}{k})$(對每種大於k的蔬菜預處理)
+$O(n^2*k*log^3n)$(每種蔬菜都恰好接近k個的時候,總的點對最多,對這些點對的預處理)
+$O(q*(\frac{n^2}{k}+log^3n))$(每次詢問對於兩部分的查詢)
由均值不等式,可以得到當$k=\sqrt\frac{n^2+q}{log^3n}$時取得最優的復雜度。
另外記yxs巨神不用容斥的做法:
將每一個點對$(x_1,x_2,y_1,y_2)$化作點$(x_1,y_1)$在點$(x_2,y_2)$左上方的形式。
那么詢問的限制轉化為:
$x<=x_1$ $x_2<=X$
$y<=y_1$ $y_2<=Y$
因為$x_1$已經排序,自動滿足限制。
$x_2$,$y_2$都是小於等於某個值的限制,只要將$y_1$翻轉就可以直接查三維前綴和統計答案。
C. 聯盟
可以說是三道題里最簡單的一道。
首先,題中定義的危險程度,樹上最遠兩點距離,即樹的直徑。
那么問題被轉化成割掉樹上一條邊,求如何用一條邊連接兩棵樹使新樹的直徑最小。
顯然最優決策一定是連上兩棵新樹的直徑中點,因為任何改變位置都會使新樹的直徑更長。
於是問題轉化成如何求原樹上,割掉一條邊之后兩棵新樹的直徑。
正常的思路都是選節點1作為根節點,進行dfs求出子樹直徑。
然而問題是,有一些聯通塊無法被1的子樹表示出來。
那么考慮轉化思路,我們分別以樹上一條直徑的兩個端點作為根節點,求出子樹的直徑。
於是分類討論就可以了:
1.割掉非直徑邊:那么直徑所在聯通塊的直徑就是原樹的直徑,另一側的直徑可以被任意一個dp數組表示出來。
2.割掉直徑邊:那么兩個dp數組分別表示一個聯通塊的直徑。
最后隨便選一條符合的答案,抽出兩條直徑連中點就可以了。