分块 + 斜率优化.
考虑分块,对于每一块维护块内的 $\max\lbrace a_i\cdot b_i\rbrace$ ,以及加法标记 $tag$ .
每次 $tag$ 被更新后,需要重新计算块内的 $\max\lbrace a_i\cdot b_i\rbrace$ .
此时每个位置实际的值是 $c_i=tag\cdot b_i+a_i\cdot b_i$ ,要找出最大的 $c_i$ .
这是个斜率优化的形式,写成 $-a_i\cdot b_i=tag\cdot b_i-c_i$ .
块内每个点横坐标为 $b_i$ ,纵坐标为 $-a_i\cdot b_i$ ,用一条斜率为 $tag$ 的直线去截这些点,需要最小化截距.
把它们按照 $b_i$ 从小到大排序,维护一个下凸壳,用斜率为 $tag$ 的直线去截它就可以得到答案.
由于 $tag$ 只会不断增大,每次被截到的点不可能向左移动,于是不需要在凸壳上二分,不断尝试将答案向右移即可.
对于边角部分,把块重构之后暴力询问答案.
交换操作容易处理,将影响到的两个块重构一下就可以了.
每次重构需要将该块重新按 $b$ 排序.
设块大小为 $B$ ,则复杂度为 $O(n\cdot(\frac n B+B\log B))$ ,取 $B=\sqrt \frac{n}{\log n} $ ,得到时间复杂度 $O(n\sqrt{n\log n})$ .
每次重构时最多只会有 $2$ 个元素的 $b$ 是无序的,若直接用归并排序重构,时间复杂度 $O(n\sqrt n)$ .
空间复杂度 $O(n)$ .
1 | //%std |