CF627E Orchestra

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

,,时限 。


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

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

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

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

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

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

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

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

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

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

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

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

此时的复杂度即为 。