【做題記錄】ds合集 Part III

FantasyNumber發表於2024-10-18

ds 合集的 Part 3,此合集包含貪心問題。

貪心問題

CF30E

題目連結

考慮對一個 \(a'\) 找到其對於的 \(a\),肯定是越前越優,那麼拿 \(S\) 的反串做個 kmp 即可得到每個 \(a\) 的第一次出現位置。然後就是在區間中找最長的奇迴文串,manacher 預處理,然後二分半徑 \(len\),看看 \([l+len-1,r-len+1]\) 是否存在 \(p_i \ge len\) 即可,st 表維護。複雜度 \(\Theta(n\log n)\)

CF187E

題目連結

特判 \(l=0,1\)

由於最左、最右都要去,所以答案有個明顯的下界是 \(\min(x_s -x_1,x_n - x_s)+x_n-x_1\)。假設取到 \(x_s-x_1\)(可以翻轉再做一遍),那麼最優肯定是要從 \(s\) 先往左走到 \(1\),然後跳到 \(s+1\) 再一直往右走到 \(n\),但會出現左票不足或過多的情況。

  • 左票不足:那就是先往左走幾步,然後跳到 \(1\),往右走回來的時候再走那些沒走過的。
  • 左票太多:那就是 \([s+1,n]\) 這些位置有些要透過左票到達,那一個點在 \(s\) 右邊且被左票到達肯定是往右走到了某個點然後往回走到了它,這時有可能是從 \(n\) 往回走的,那麼 \([x_i,x_{i+1}]\) 這段區間只用走 \(2\) 次,否則就要走 \(3\) 次,那麼列舉終點在哪裡,找到 \(s\) 到終點這段區間中前 \(k\) 小的區間換成左票即可,\(k\) 是左票剩的減去從 \(n\) 走回終點的。

可以用平衡樹或線段樹維護前 \(k\) 小,複雜度 \(\Theta(n\log n)\)​。

CF196D

題目連結

考慮找到原串最大位置 \(pos\) 使得 \(s[1,pos]\) 沒有長度大於等於 \(d\) 的迴文子串,然後從 \(pos\) 開始嘗試替換。注意到只用考慮長度為 \(d,d+1\) 的迴文串,因為 \(d+2,d+3\) 的包含 \(d,d+1\) 的。如果 \(pos\) 往前某個位置替換成一個字元後,以它結尾的 \(d,d+1\) 的串都不是迴文串,那就開始往後加字元,直接暴力列舉判斷是否合法即可。複雜度 \(\Theta(nc)\)​。

CF436E

題目連結

考慮反悔貪心,每次新增一個星星,有幾種情況。

  • 從選了一個的加上 \(b_i- a_i\)
  • 從沒選的加上 \(a_i\)
  • 從選了一個的和沒選的加上 \(-a_i + b_j\)
  • 從選了兩個的和沒選的加上 \(a_i - b_i + b_j\)

用五個堆維護最小的 \(a_i,b_i,-a_i,a_i - b_i,b_i - a_i\) 即可,複雜度 \(\Theta(n\log n)\)

CF524F

題目連結

\(cnt0,cnt1\) 為刪掉原括號串的所以合法括號子序列後的 \((\)\()\) 的個數,顯然最少新增 \(|cnt0-cnt1|\) 個括號。考慮操作 \(2\),就是要求一個字典序最小的迴圈同構,使得這個迴圈同構也只需要 \(|cnt0-cnt1|\) 個括號,先不管原串中所有沒匹配的字元,這個迴圈同構的起點一定是原串某個合法括號子段的開頭,列舉這個位置,再看看這樣迴圈移位後原來沒匹配的那些字元還需要新增多少個,若為 \(|cnt0-cnt1|\),那麼這個位置就是可能可行的。

考慮所有可行的位置,要找到字典序最小那個,就把原串複製一遍接到後面,然後字尾排序即可。使用 SA 常數較大,可能無法透過,使用 SAM 可以做到 \(\Theta(n)\)

複雜度 \(\Theta(n)\)\(\Theta(n\log n)\)

CF625E

題目連結

按照位置排序後顯然每個沒被刪掉的人相對位置不會改變,可以用連結串列維護這個相對位置。然後每個人先刪的肯定是它下一個人,那就對每個人維護刪掉它後一個人至少需要多少輪,把它放進一個小根堆裡面,每次取出堆頂的人,記錄時間 \(t\),從它開始一直往後刪,直到需要的時間大於 \(t\) 停止,記錄被刪的人數。每次把所有 \(t\) 相同的人拿出來,這樣更新後,更新它們的速度,並且記錄每個人上次更新速度的時間(用現在的時間減去上次更新的時間乘上速度就是當前的位置)。然後再對這一輪 \(t\) 相等的人找到它們上一個人和下一個人,更新刪掉它或刪掉其他人的時間,繼續放到堆裡面。模擬這個過程即可,複雜度 \(\Theta(n\log n)\)

CF671D

題目連結

考慮權值都是 \(1\) 怎麼做,顯然從深的往淺的遍歷每條邊,如果遇到一條邊沒被覆蓋,就找到能覆蓋到這條邊的且 \(y\) 最淺的那條邊選擇。

考慮權值任意,此時依然從深往淺做,並且每次取權值最小的那條路徑。當然,直接這樣是顯然錯誤的,因為權值小的路徑深度可能不如權值大的淺。那麼就可以考慮一個反悔貪心的過程,每次依然貪心地選擇權值最小的,並且把 \(x\) 在這個權值最小的路徑的 \(x\) 下方或等於它的所有路徑的 \(x\) 設為這條路徑的 \(y\),把它們的權值減去當前選的這條路徑。

實現可以考慮從下往上合併,並且記錄還能往上覆蓋幾條邊和下方的所有沒被選的且 \(y\) 在這個點上方的路徑,還要支援單點修改和整體減。可以考慮線段樹合併或平衡樹來維護這個東西。複雜度 \(\Theta(n\log n)\)\(\Theta(n\log^2 n)\)

CF797F

題目連結

注意到把老鼠和洞按照編號排序,每個洞進的老鼠一定是一段連續的區間,設 \(dp_{i,j}\) 表示前 \(i\) 個洞進了前 \(j\) 個老鼠,設 \(sum_{i,j}\) 為洞 \(i\) 到前 \(j\) 個老鼠的距離和,轉移有 \(dp_{i,j} = \max\limits_{k=\max(0,j-c_i)}^{j} dp_{i-1,k}+sum_i - sum_k\),顯然可以單調佇列最佳化。

複雜度 \(\Theta(nm)\)

CF935F

題目連結

這裡設 \(a_i\) 為原來的 \(a_i - a_{i-1}\),那麼 \(f(a)=\sum\limits_{i=2}^n |a_i|\)

考慮操作 \(1\),特判邊界。即在 \(a_l\)\(a_r\) 中選一個 \(a_i \leftarrow a_i + x,a_{i+1} \leftarrow a_{i+1} -x\)。討論一下有哪些情況,設 \(ans\) 為選擇一個位置加上 \(x\) 後和原序列答案的差。

  • \(r-l+1\le 3\),直接暴力跑一下
  • \(\exist i,a_i \ge 0,a_{i+1} \le 0\),則 \(ans=2x\),是最優的情況。
  • \(\exist i,a_i \ge 0,a_{i+1} \ge 0\),可以發現 \(ans\) 總非負。
    • \(a_{i+1} \le x\),則 $ans = 2(x-a_{i+1}) $。
    • \(a_{i+1} \ge x\),則 \(ans=0\)
  • \(\exist i,a_i \le 0,a_{i+1}\le 0\),可以發現 \(ans\) 總非負。
    • \(a_{i} \ge -x\),則 \(ans = 2(x+a_i)\)
    • \(a_{i} \le -x\),則 \(ans=0\)
  • \(\exist i,a_i \le 0,a_{i+1} \ge 0\),可以發現只要 \(a_i \le -x \lor a_{i+1} \ge x\),那麼 \(ans\) 一定非正,所以只用考慮 \(a_i \ge -x \land a_{i+1}\le x\),此時 \(ans=2x + 2(a_i - a_{i+1})\)

綜上,當長度大於 \(3\) 時,必定出現正負或正正或負負,\(ans\) 一定非負,只需要維護所有滿足條件的 \(-a_{i+1},a_i,a_i - a_{i+1}\) 的最大值即可,用線段樹維護,複雜度 \(\Theta(n\log n)\)

CF1051G

題目連結

考慮單個序列怎麼做,因為把一個數變少可以得到 \(-b_i\) 的價值,那先儘可能地減少一定是不劣的。如果有若干個相同的 \(a_i\),那麼肯定是最後讓 \(b\) 最小的 \(a\) 最大,\(b\) 最大的 \(a\) 最小,這是容易的。但是整個序列有可能不能都變成同一種值,會分成若干段,每個極長段的形成是先把小的數變大,形成一個區間,被這個區間包含的數繼續擴充這個區間,直到不能擴充為止。統計的話是容易的。

考慮對每個字首求答案,那可以維護前面的若干值域連續段,顯然加一個數最多新增一個段,有可能合併兩個段。一個段內肯定是先把所有數變成這個段裡的最小值,然後把它們的 \(b\) 排序,代價就是 \(-\sum\limits_i (a_i -minx)b_i+\sum\limits_i b_i(len-rk_i)\)\(-\sum\limits_{i} (a_i - minx+rk_i)b_i+len\sum\limits_i b_i\)\(rk_i\) 的處理可以用線段樹合併來做。複雜度 \(\Theta(n\log n)\)

CF1137E

題目連結

顯然只用管每次插入的第一個數,且每次進行操作 \(1\) 之後只用考慮第一段的第一個數。當進行操作 \(2\) 的時候,會暫時性地使最小值變成最後一段的第一個,但是這個影響會隨操作 \(3\) 而逐漸消去,因為最後一段的下標大。

考慮維護一個不增的結構,對於相鄰的兩個下標 \((x,y)\),每次進行操作 \(3\) 會使 \(a_x - a_y\) 減少 \(s(y-x)\),而 \(x,y\) 是固定的(因為操作 \(1\) 之後會把整個結構清空),所以記錄 \(t_x = \lceil \dfrac{a_x - a_y}{y-x} \rceil\) 表示 \(s\) 至少為 \(t_x\)\(a_x\) 會比 \(a_y\) 小。用連結串列+小根堆維護這個結構,每次往後插入後在連結串列最後插入一個 \(0\),並把倒數兩個的 \(t_x\) 插入到堆裡面。每次進行操作 \(3\) 時看看堆頂是否已經足夠了,就將其刪除。操作 \(1\) 直接情況即可。複雜度 \(\Theta(n\log n)\)

CF1238G

題目連結

考慮將所有人按照時間排序,到時間 \(i\) 時先把能買的都買了,先不付款,每次從 \(lst\) 走到時間 \(i\) 時,取前 \(i-lst\) 小的付款。但是會有容量限制,不能無限制地買,那麼買 \(i\) 時如果已經滿了,可以把前面還沒用到的價格比 \(i\) 大的取消購買,反悔貪心。注意到每次從一個人走到下一個人要麼只買以前一個人的,要麼就至少買空一個人,所以一共只會買 \(\Theta(n)\) 段相同的。用堆維護價格最小值和最大值,並用一個陣列記錄每個人能用的有多少即可。複雜度 \(\Theta(n \log n)\)​。

CF1446D2

題目連結

注意到所有極長的擁有 \(2\) 個以上眾數的段一定以全域性眾數為眾數之一。證明:若全域性眾數不為其眾數,可以擴充左右端點直到全域性眾數的出現次數等於其眾數的出現次數。那麼如果全域性眾數有不止 \(1\) 個,答案即為 \(n\),否則設其為 \(x\)。考慮答案子區間的眾數出現次數 \(cnt\)

  • \(cnt>B\),只用考慮所有出現次數 \(>B\) 的數,有 \(\Theta(\dfrac{n}{B})\) 個,考慮列舉這些數 \(i\),把 \(x\) 設為 \(1\)\(i\) 設為 \(-1\),找到一個極長的段使得和等於 \(0\) 即可,用一個桶記錄字首和第一次出現位置,複雜度 \(\Theta(\dfrac{n^2}{B})\)
  • \(cnt \le B\),考慮列舉這個出現次數 \(i\)。從左往右列舉答案的右端點 \(r\),雙指標記錄 \(x\) 出現次數為 \(i\) 的合法做端點 \(l\) 的區間,對於其他數也這樣做,最小的 \(l\) 就是所有其他數的 \(l\) 區間和 \(x\)\(l\) 區間交的最小值。複雜度 \(\Theta(nB)\)

複雜度 \(\Theta(n\sqrt{n})\)

CF1469F

題目連結

考慮二分答案,然後按長度從大到小排序,依次從淺到深加入,每次加入一條鏈時儘量把連線點放到中心。每次連線中心是顯然的,因為讓 \(\le mid\) 的白點儘可能淺來接其他鏈。從大到小加入是因為每次連結的上面那個白點的深度是單調不降的,所以肯定讓深度淺的時候能貢獻更多,如果在深一點的地方接大的就會造成浪費了。差分維護一下即可,複雜度 \(\Theta(n\log n)\)

CF1503D

題目連結

考慮無解的必要條件,若存在 \(a_i,b_i \le n\),那麼必定存在一個 \(a_j,b_j > n\),顯然無解。那麼有解必然對於所有的 \(i\) 使得 \(a_i \le n,b_i > n\)\(a_i > n,b_i \le n\)

\(i \in [1,n]\) 對應的另一邊(比它大的數)是 \(f(i)\),那麼答案就是若干個 \(i\) 升序排列,其對應的 \(f(i)\) 降序,然後接上 \(f(i)\) 升序,\(i\) 降序。其中前面那段的 \(i\) 在反面的貢獻為 \(1\),後面那段的 \(i\) 在正面貢獻為 \(1\)。那麼按照 \(i\) 排序,就是要讓 \(f(i)\) 分成兩個下降子序列。

考慮判斷是否有解,貪心地將新的 \(f(i)\)​ 加入前面兩個下降子序列中最後一個數較小的且大於它的那個子序列中,但這樣可能並不是最優解。

考慮什麼時候一個數可以加入前面兩個序列,結論:\(\min\limits_{j=1}^i a_j > \max\limits_{j=i+1}^n a_j\) 時,會有多種方案,這是顯然的。那麼考慮按照這個把原序列分段,每段有唯一分組方案,只是不知道哪個是前面的一段,哪個是後面的一段,顯然討論一下取最小即可。複雜度 \(\Theta(n)\)

CF1539F

題目連結

考慮中位數的經典套路,假設當前在求 \(x\) 的答案,先假設當前區間中只有一個 \(x\),把 \(<x\) 的數看成 \(1\)\(>x\) 的數看成 \(-1\),把 \(x\) 看成 \(0\) 那麼 \(x\) 的距離就是這個區間的和除以 \(2\) 向下取整的絕對值。那麼如果有多個 \(x\),把一個 \(x\) 看成 \(0\),把其他的全看成 \(1\) 或者 \(-1\) 一定是最優的。因為考慮只有一個 \(x\) 時,若 \(x\) 排序後在中位數左邊,加入一個 \(x\) 會使中位數位置往右移動,最左邊那個 \(x\) 一定是最遠的,\(x\) 在右邊時同理,最右邊肯定是最遠的。

考慮掃描值域,用線段樹維護字首和,每次修改一個字尾,詢問 \(i\) 時先把所有 \(a_j = a_i\)\(j\) 修改為 \(1\)\(-1\) 都做一遍,詢問 \(i\) 右邊最大值減去左邊最小值,和右邊最小值減去左邊最大值(因為有負數的情況)取最大即可。複雜度 \(\Theta(n\log n)\)

CF1566F

題目連結

首先把所有已經包含點的區間扔掉,那麼現在就剩一堆點然後一堆區間然後一堆點這樣子。考慮每個點是怎麼走的,可以先往左邊走再回來再往右邊,也可以先往右邊再回來再往左邊,也可以直往一個方向走。考慮兩個相鄰的點之間的區間,顯然這些區間只可能被這兩個點其中一個走,將它們按照左端點排序,左邊那個點走的就是一個字首的左端點最大值,右邊的點走的就是字尾的右端點最小值。

\(dp_{i,0/1}\) 表示做完前 \(i\) 個點,其中第 \(i\) 個點是不是先往右走(或者不往右走)。轉移的話直接列舉上個點走到那個字首,算一下字尾 \(\min\) 即可,\(dp_{i,1}\) 的話要來回走,所以注意貢獻要加兩次。複雜度 \(\Theta(n\log n)\),在於排序。

CF1601D

題目連結

有個樸素的想法是全部按 \(a_i\) 排序,先取 \(a\) 小的,但是發現這樣是錯誤的,因為有些是 \(s_i < a_i\) 的可以先取,然後還有 \(s_j \ge a_j\) 的後取,而 \(s_i < a_j \le a_i \le s_j\)。那麼可以嘗試將人分成兩類,\(s_i < a_i\) 的和 \(s_i \ge a_i\) 的。

還是根據剛剛的想法,設 \(f_i\) 為當前高度為 \(a_i\) 時的答案,把人按照 \(a_i\) 排序。特殊地,對於 \(s_i < a_i\) 的人的 \(f_i\),除了 \(a_j \le s_i\)\(f_j\) 的最大值的貢獻,還有 \(s_i < a_k \le a_i \le s_k\) 的所有 \(k\) 的貢獻,那麼只要算出有多少個 \(k\) 就行,二維數點 bit 維護。複雜度 \(\Theta(n\log n)\)

CF1601E

題目連結

考慮單次詢問,從 \(l\) 開始,在 \(l,l+k,l+2k\cdots\) 位置都買一張 \([l,l+jk]\) 的最小值即可。

考慮多次詢問,把所有 \(l \operatorname{mod} k\) 同餘的 \(l\) 一起做,從後往前掃描線。維護所有 \(p \operatorname{mod} k = i\) 的所有位置的答案,當掃描到 \(l\) 的時候,\(ans_l\) 設為 \(a_l\),然後找到 \(cur=\min\limits_{j=l}^{l+k-1} a_j\),把 \(l+k,l+2k,l+jk\) 的所有大於 \(cur\)\(ans\) 換成 \(cur\) 即可,單調棧維護。查詢 \(l\) 對應的 \(r\) 時找到最大的 \(j\) 使得 \(l+jk\le r\),把 \([l,l+jk]\) 的所有關鍵點的 \(ans\) 加起來即可。複雜度 \(\Theta(n\log n)\),在於 st 表。

CF1621F

題目連結

先把連續兩個 \(0\)\(1\) 的個數找出來,分別是 \(x,y\)。然後分討一下,記 \(cnt_0,cnt_1\) 為總 \(0,1\) 的個數。

  • \(x<y\)

顯然操作序列肯定是形如 \(2121\cdots21(232323)2\),括號處取到當且僅當 \(b>c\)。當取完連續兩個 \(0\) 後序列一定長成若干個 \(1\) 連著一個 \(0\) 再有若干個 \(1\),那就把首位的 \(0\) 去掉剩下 \(t\)\(0\),那麼當 \(b>c\) 時顯然可以把這 \(t\)\(0\) 都刪掉,此時剩下的 \(y\) 不會變,還會剩下首位的 \(0\) 能取就取就行。所以答案是 \(x \times (a+b) + \max(0,b-c) \times (t+\min(y-x-1,cnt_0 - t)) + b\)

  • \(x\ge y\)

操作序列是形如 \(1212\cdots 12(323232)[1]\),小括號取到當且僅當 \(b>c\),中括號取到當且僅當 \(x>y\)。考慮小括號中最多取到多少個 \(32\),那把相鄰兩個 \(1\) 中間的 \(0\) 個數統計出來,去掉 \(0\) 的,把剩下的排序。在前 \(y\)\(12\) 操作中可以儘量把中間連續的 \(0\) 變成一個 \(0\),即設連續長度為 \(cnt_1 \le cnt_2\le \cdots \le cnt_k\),從頭開始取 \(cnt_i - 1\) 貪心能取就取即可,設最多把 \(t\)\(cnt_1\) 變成 \(1\),答案即 \(y \times (a+b) + \max(0,b-c) \times t + [x>y]a\)

複雜度 \(\Theta(n\log n)\)​,在於排序。

CF1635F

題目連結

\(L_i\)\(i\) 左邊最大的 \(j\) 使得 \(w_j \le w_i\)\(R_i\)\(i\) 右邊最小的 \(j\) 使得 \(w_j \le w_i\)。那麼答案一定是 \((i,L_i),(i,R_i)\) 的形式。證明:設答案為 \((i,j),i \neq L_j\),那麼 \(x_i < x_{L_j} <x_j,w_i + w_{L_j} \le w_i + w_j\),因此 \((i,L_j)\) 更優。右邊的情況同理。預處理這些點對,二維數點即可。複雜度 \(\Theta(n\log n)\)

CF1672H

題目連結

\(00\) 個數 \(x\)\(11\) 個數 \(y\),每次刪除一個區間,若為 \(0(10101010)1\)\(1(01010101)0\)\(x,y\)\(1\),若 \(1(01010)1\)\(0(1010101)0\),則 \(x\)\(y\)\(1\)。顯然第一種更優,答案就是 \(\max(x,y)+1\),字首和即可。複雜度 \(\Theta(n)\)

CF1699E

題目連結

考慮掃描最小值 \(l\),對每個數去看它拆開後最大值最能到多少。貪心是錯誤的,那麼考慮 dp,設 \(dp_{i,j}\) 為最小值為 \(i\)\(j\) 能分到最大值最小是多少,從大到小轉移,\(dp_{i,j} = \max(dp_{i+1,j},dp_{i,\frac{j}{i}})\),後面那個轉移當且僅當 \(i|j\)\(j\ge i^2\) 時成立,所以只有 \(i\) 的倍數會改變,那麼直接轉移是 \(\Theta(m\log m)\) 的。考慮求答案,\(ans = \min\limits_i(\max(dp_{i,j}) - i)\),注意到 \(j\) 相同是 \(dp_{i,j}\)\(i\) 降低是單調不增的,所以可以用個桶記錄值用個指標掃就行。複雜度 \(\Theta(m \log m)\)

CF1793E

題目連結

顯然肯定是 \(a\) 最小的幾個符合要求,因為如果有 \(x<y\)\(x\) 沒滿足 \(y\) 滿足了,交換 \(x,y\) 肯定更優。那考慮二分答案,要讓前 \(mid\) 個符合要求,後面 \(n-mid\) 都去讀沒人讀的書了,這時有兩種情況。

  • \(n-mid \ge k\),此時所有書都有人讀,那麼前 \(mid\) 個人讀一本書就行了,而且這本書還有後 \(n-mid\) 個人中的 \(n-mid-k+1\) 個人讀,所以只要 \(n-mid-k+1+mid\ge a_{mid}\) 即可。
  • \(n-mid<k\) 此時還有 \(k-n+mid\) 個書要讀,設 \(f_i\) 為前 \(i\) 個人都滿足要求最多讀幾本書,顯然 \(f_i = \max\limits_{j\le i-a_i} f_j + 1\)。所以只要 \(f_{mid} \ge k - n +mid\) 即可。

複雜度 \(\Theta(n+q\log n)\)​。

CF1720E

題目連結

設一開始有 \(m\) 個顏色。

  • \(m<k\),顯然答案等於 \(k-m\)
  • \(m>k\),下面證明答案不超過 \(2\)
    • 第一個矩陣以 \((1,1)\) 開頭擴充,把這個矩陣變成一個已有的顏色,擴充到最大的 \((t,t)\) 使得 \(m'\ge k\)
    • \(m'>k\),第二個矩陣從 \((t+1,t+1)\) 往左上擴充,變成和第一個矩陣一樣的顏色,每次覆蓋 \(2\) 個,所以最多使 \(m'\)\(2\)
    • 若最終的 \(m'=k-1\),那麼把第二個矩陣的顏色變成一個沒出現的顏色即可。
    • 判斷答案等於 \(1\):可以先列舉長度 \(len\),然後對於每種顏色,算出它的最小、最大的 \(x,y\),顯然符合要求的左上角是一個矩陣,差分一下就行。

複雜度 \(\Theta(n^3)\)​。

CF1844F1

題目連結

注意到 \(c\ge 0\) 時從小到大一定是最優解,\(c<0\) 時從大到小是最優解,但是字典序不一定最小。那就從前往後考慮每一個 \(a_i\),列舉後面的 \(a_j\) 看看能否把 \(a_j\) 放到 \(a_i\) 前面,令 \(f(x)=|x-c|\),只需判斷 \(f(a_j - a_{j - 1}) + f(a_{j+1} - a_j) + f(a_i - b_{i-1})-f(a_{j+1} - a_{j-1})-f(a_j - b_{i-1})-f(a_i - a_j)=0\) 即可,\(b_{i-1}\) 是已經確定的位置。複雜度 \(\Theta(n^2)\)

F2 的結論沒看懂/kk

CF1893D

題目連結

考慮對於一個單獨的 \((s,d)\) 應該怎麼填,肯定是以長度 \(d\) 為一個區間,每個區間的數都不相同。

貪心地,考慮先滿足 \(d\) 大的 \((s_i,d_i)\),然後先用數量最多的 \(d\) 個顏色,先放 \(d\) 個,然後再重新取當前數量最多的 \(d\) 個顏色再放,重複這個過程。先用最多的原因是若用了數量少的,那麼那個顏色可能以後就不能用,我們肯定希望當前可用的顏色種類越多越好。考慮模擬這個過程,先把所有顏色放到大根堆裡面,然後每次就取出堆頂的 \(d\) 個彈出,然後把它們的個數減 \(1\) 塞回去,再重新取 \(d\) 個即可。

複雜度 \(\Theta(n\log n)\)

CF1919F2

題目連結

考慮將水看成流,其實就是一個網路流模型,\(s\to i,a_i\)\(i\to t,b_i\)\(i\to i+1,c_i\)。單點修改問最大流,顯然可以貪心流,能流到 \(t\) 就流到 \(t\)

考慮兩個區間怎麼合併,需要知道什麼。可以維護區間的幾個資訊:從這個區間流到右邊的流大小,這個區間剩餘的 \(b_i\) 之和,從左邊能流入最大的流使得不能再流了,還有答案分別記為 \(out,rem,in,ans\)。合併的時候,\(ans=ans_1 + ans_2 + \min(c_{r_1},out_1,in_2,rem_2)\)\(in=\min(in_1,rem_1+c_{r_1}-\min(out,c_{r+1}),rem_1+in_2-\min(c_{r_1},out_1,in_2))\)\(out=\max(0,\min(c_{r_1},out_1,in_2)-rem_{2})+out_2\)。線段樹維護即可,單點修改,全域性查詢。

複雜度 \(\Theta(n\log n)\)