Ynoi 2077 3dmq
这个修改实际上就是点加,询问就是点和。所以很好拆贡献。
操作分块,根号重构
因为询问的答案只会来自之前操作的修改。
我们对操作序列分块,块长
类型一: 同块内在这个询问之前的修改
类型二:在这个询问之前的块的修改
然后这个题的大体思路就是
- 第一类贡献计算:分别处理每个操作块(未重构部分)
- 第二类贡献计算:用一个全局数据结构
- 在扫完一个块就把这个块修改的贡献加进去(重构)
- 使用那个全局数据结构对每个点计算第二类贡献(已重构部分)
三维数点
指的是这样一个问题:对于若干个点
然后我们把这三个部分都转化为三维数点问题。然后三维数点就用二维分块做。
大概就是用一个全局二维分块,从小到大枚举
我们知道二维分块点修矩阵查和矩阵修点查都可做,并且可以把修改和询问的复杂度控制为
- 三维数点
O(n) 个点O(\sqrt n) 个询问,应该用O(1)-O(\sqrt n) 二维分块(显然) - 三维数点
O(\sqrt n) 个点O(n) 个询问,应该用O(\sqrt n)-O(1) 二维分块(还是显然)
已重构部分
在每个询问块开始之前,(用一个能做三维数点的数据结构)维护好此时每个点的
然后拿这个块的
因为有
重构部分
这部分相当于把
我们还是三维数点,但是把询问当做点,点当做询问。三维数点做的是:对于每个点,有几个修改会对它产生影响。
对于这个三维数点而言,“点”数是询问数的
未重构部分
这次对于每个询问,只需要考虑和它一个块内的修改。
所以我们大可以分析一个修改对一个询问的贡献,因为这样的一对只有
- 考虑修改
\{x,y,z,w_0\} ,询问\{X,Y,Z\} 。(首先他俩得同块且修改在询问前面) - 对于一个点
\{u,v,w\} ,权值分别为a,b 。 - 如果
u\le x,u\le X,v\le y,v\le Y,w\le z,w\le Z ,产生w_0\times a 的贡献 - 综合起来,就是在
\min(x,X),\min(y,Y),\min(z,Z) 三维偏序中的点,他们的a 之和乘上修改的w_0 。
那就相当于
因为只用做一次,所以可以有
三维数点
首先考虑重构部分和未重构部分的二维分块。这个结构参考
- 【整块】红色正方形
n^{\frac 34}\times n^{\frac34} - 【整块】橙色长方形
n^{\frac 12}\times n^{\frac34} - 【整块】黄色长方形
n^{\frac 34}\times n^{\frac12} - 【整块】绿色正方形
n^{\frac 12}\times n^{\frac12} - 【散块】紫色粉色长方形窄的边
<n^{\frac12} - 【散块】蓝色长方形长和宽都
<n^{\frac12} - 整块维护块和
- 散块借助 点
x,y 轴坐标互不相同 性质,所以看起来很大的散块只会有O(\sqrt n) 的总点数,枚举点计算即可
然后是重头戏。未重构部分的三维数点。这个三维数点和上面那个结构不太一样。
原因是询问有
如果按正常方法写,为了做到询问
在这种情况下,依赖每个
所以我们整块散块分开做,整块还是维护那四种矩形的和。
对于上述整块,因为它只能查整块的和,所以我们不妨抽象地把一个
然后我们考虑散块,根据上面那个图,散块分为粉色、紫色的大散块,和蓝色的小散块。
因为小散块的定义,所以将原平面划分为
因为有
大散块就复杂一些,我讲讲紫色竖条怎么做,粉色横条类似。
这里我们枚举每个像绿色这样的
绿色矩形中会有
然后我们意识到现在原问题被简化了:
- 只有
O(\sqrt n) 个修改,O(n) 个询问 - 横轴因为是散块,只有
\sqrt n 的范围 - 纵轴因为是整块,所以我们可以用块编号代替它的位置,也只有
\sqrt n 的范围。
而根据我上面所说,二维分块做整块可以支持对一个
但是这些操作怎么排序?排序会多
对于点和询问分别的排序,我们把每个 vector 装一下就排好了。然后它们在归并一下,或者说双指针一下,就可以按顺序来做了。
(2022.12.20)代码是五个月前写的,断断续续写了一个月,特别不可读。最近有点忙,等有空了我回来重构,重构完的代码会放到 这里。
因为没有代码。如有不理解欢迎私信询问。