T1:
原題連結
orz 盜版說的道理
T2:
原題連結
不難發現,設最終每段黑白比值為 \(C\),則 \(\frac{\sum W}{\sum B}=C\),我們可以直接算出每段的黑白格子比值為多少。
接下來考慮如何讓劃分割槽間最多:
-
結論: 一定是恰好滿足 \(\frac{W}{B}=C\) 的最小的區間。
-
證明: 設 \([1,x],[1,y]\) 區間均滿足條件,且 \(x<y\),發現 \(\frac{W_{1,x}}{B_{1,x}}=\frac{W_{1,y}}{B_{1,y}}=\frac{W_{x+1,y}}{B_{x+1,y}}\),所以選 \([1,y]\) 不如選 \([1,x],[x+1,y]\),能產生更多貢獻。
接下來模擬上述貪心過程即可。
T3:
原題連結
棋盤上放置方案問題,很容易想到動態規劃求解,觀察資料範圍,無法狀態壓縮。
但再觀察,發現某一列上最多隻能放兩個棋子,某一行也同理,所以我們可以這樣設計狀態:令 \(f_{i,j,k}\) 表示前 \(i\) 行,有 \(j\) 列放了一個棋子,\(k\) 列放了兩個棋子的方案數。
轉移時列舉第 \(i\) 行放了多少棋子:
-
不放棋子,直接從上一行狀態轉移來:\(f_{i,j,k}=f_{i-1,j,k}\)。
-
放一枚棋子,它可以放到之前沒有棋子的和有一枚棋子的列:\(f_{i,j,k}=\begin{cases}f_{i-1,j-1,k}\times (m-(j-1)-k)\\f_{i-1,j+1,k-1}\times (j+1) \end{cases}\)
-
放兩枚棋子,可以都放到沒棋子的列,都放到放一枚棋子的列,以及分別放沒棋子和有一枚棋子的列。
轉移方程為:\(f_{i,j,k}=\begin{cases}f_{i-1,j-2,k}\times C_{m-(j-2)-k}^{2} \\f_{i-1,j+2,k-2}\times C_{j+2}^{2}\\ f_{i-1,j,k-1}\times j\times (m-j-(k-1)) \end{cases}\)
最後答案為 \(\sum_{j=0}^{m}\sum_{k=0}^{m}f_{n,j,k}\)。
T4:
原題連結
可以暴力列舉 \(a,b\),然後 \(c\in [2b-a,n]\),找區間最大值即可。
對於我們選擇的 \(a,b\) 間,若能在 \((a,b)\) 中找到某個下標 \(i\),滿足 \(h_i\ge h_a\) 或 \(h_i\ge h_b\),那麼選擇 \(i\) 是更優的。
理由很簡單,無論是從 \(a\to i\) 還是從 \(b\to i\),都會擴大 \(c\) 的選擇區間,同時還能增大你的 \(h_a+h_b\)。
所以我們只找滿足以下條件的 \(a,b\):
- \([a,b]\) 中最大值 \(< \min\{h_a,h_b\}\)。
這不就是找到一個數,它左右兩邊的最近的大於等於它的數嗎。直接單調棧求出,並且這樣的數對是 \(O(n)\) 級別的。
然後我們把詢問離線下來,從大到小列舉左端點進行掃描線,對於新的左端點 \(i\),先把預處理來的數對 \((a,b),a=i\) 對答案進行更新。
如何維護答案?考慮線段樹,設 \(B_i\) 表示如果選 \(i\) 作為 \(c\),它左邊的最大的 \(h_a+h_b\),對於新來的數對 \((a,b)\),將 \([2b-a,n]\) 中的 \(B_i\) 與 \(h_a+h_b\) 取 \(\max\),這個用線段樹很好維護。
對於左端點為 \(i\) 的所有詢問,查詢區間 \([i+2,r]\) 的 \(B_i+h_i\) 的最大值。
所以線段樹維護 \(h_i,B_i+h_i\) 的最大值,支援與某個數取 \(\max\) 操作,這道題就做完了。
時間複雜度 \(O((n+q)logn)\)。