P3722 [AH2017/HNOI2017]影魔

首先,我们发现这个有贡献的数对可以有 \(O(n^2)\)。(显然你构造一个升序就行了)

然后,这就说明我们肯定不能把这些贡献一个个算出来丢到平面上。考虑到贡献只有 \(p_1,p_2\) 两种,考虑把相同的丢到一起去算。

对于数对 \((l,r)\),我们去考虑区间 \([l+1,r-1]\) 的最大值所在位置为 \(p\),想一想同样的 \(p\) 对应的数对 \((l,r)\) 有哪些贡献。

\(p\) 为最大值的最大区间为 \(L[p],R[p]\),这个可以单调栈 / 笛卡尔树。我们发现有 \(L[p]-1 \leq l < i\ ,\ i < r \leq R[p]+1\)

看一看哪些能产生贡献 \(p_1\),这要求 \((l,r)=(L[p]-1,R[p]+1)\)

看一看哪些能产生贡献 \(p_2\),这要求 \((l,r)=(L[p]-1,i+1 \dots R[p]-1)\ or (L[p]+1 \dots i-1,R[p]+1)\)

发现这些贡献一共是 \(3n\) 个矩形,我们要做的是在平面上查询正方形内的和。

这个显然可以用树套树 / 主席树之类的做。

但我们可以离线下来优化复杂度。

考虑扫描线。对一个询问 \((L,R)\),我们在扫到 \(l=R \ \& \ L-1\) 的时候分别记录一下一作差即可。

但其实对于“竖着的”矩形,我们要特殊处理一下。有两种办法:

  • 注意到题目中询问的是正方形区间内的和,我们发现“竖着的”矩形翻转过来变成“横着的”对询问的贡献是不变的。

  • 或者也可以考虑尝试加等差数列。加一会之后变成常数的等差数列可以看做两个等差数列的差,所以我们考虑怎么加等差数列。考虑这样两个 \(a_x,p_x,b_x;a_y,p_y,b_y\) 的等差数列,对当前扫到的第 \(i\) 行有什么贡献(先只考虑一格),显然是 \(i(p_x+p_y)+a_x+a_y-a_xp_x-a_yp_y\),用数组存下当前行每一个格子的这些系数即可。考虑到有区间操作,换成线段树就行了。

时空复杂度 \(O(n\log n)\)

posted @ 2023-02-21 16:54  PYD1  阅读(34)  评论(0)    收藏  举报