1. 程式人生 > 其它 >「IOI 2021」分糖果(線段樹)

「IOI 2021」分糖果(線段樹)

傳送門

分析:

離線後對序列做掃描線。相當於掃到 \(l\)\(r + 1\) 時,新增或刪除一個 \(t\) 時刻的操作。開個陣列 \(a\),把 \(t\) 時刻對糖果數量的修改量記在 \(a_t\) 上,我們要支援 \(a\) 的單點修改,以及對於容量為 \(c\) 的糖果盒的詢問。

有兩邊的限制看著不好做,考慮先去掉下界限制。發現一定有一個時刻減到 \(0\),之後不再減到 \(0\)。記 \(f(c)\) 為容量 \(c\) 的答案,記 \(g(c, i)\) 表示只考慮 \(a_i\) 開始的字尾,且可以扣到負數時的答案,那麼 \(f(c) = \max(g(c, i))\)

\(a\)

的字尾和為 \(s\),那 \(g(\infty, i)\) 就是 \(s_i\)。而 \(g(c, i)\) 還要減去 \(i\) 開始的最大字首和超過 \(c\) 的部分,也就是 \(\max(0, s_i - s_j - c)\)。因此 \(g(c, i) = \min(s_i, \min s_j + c)\)\(j \ge i\))。

我們要求 \(\max g(c, i)\)。發現只有 \(s_i\) 為字尾最大值時有用。記 \(x, y\) 分別為 \(s\) 的字尾 max 和 min,我們求的就是 \(\max(\min(x_i, y_i + c))\)。搞個線段樹二分,分段做即可。時間 \(O(n \log n)\)

提交記錄