CF627E Orchestra

题意:在一个 的矩阵中有 个点,求至少含有 个点的子矩阵个数。

,时限


首先有一个经典的 做法 : 枚举上下边界 ,从左到右枚举左边界 ,可能的右边界范围在 内,且 是单调右移的,利用二维前缀和不难 判定。

考虑到本题中 较小,也可以用基于点的做法。

若行 之间 右侧的第 近点为 (以 为第一关键字, 为第二关键字),则可能的右边界个数即为 。其中 部分是常数,只需统计 的贡献和。

对于关键点 ,记以它为右侧第 近点的左边界有 个,则贡献为

(为了处理边界情况,需要在两侧各预先加入 个边界点)

接下来考虑先枚举上边界,下边界从上到下移动,相当于每次加入一行的点。动态维护所有关键点的

对每个关键点 ,设左侧第 近点的横坐标为 ,则范围 内的左边界与 之间产生贡献。

当插入点 时,只会影响该点右侧的 个点,可以暴力更新

然后找到该点左侧的 个点,计算自己的贡献。

可以 std::set 维护并使用迭代器访问,复杂度为 ,且常数较大,难以通过。

考虑将过程反过来,将下边界从下向上移动,此时只需要删点。用双向链表维护,删除某个点容易做到

删除一个点后,可能影响的也只有右侧的 个点,线性遍历即可。

此时的复杂度即为