对祂使用根号平衡吧(十二重分块法)
前置知识:基础分块(会做分块入门九题的一半即可)。
你经常会因为写出诡异
以下默认
1. 单点修改 O(\sqrt n) ,区间查询 O(1)
可以证明,这种状物都可做,而且非常常用,我们一步步由浅入深。
1.1 单点修改,区间和
相当常见的平衡,考虑将序列按
然后你对每一个块储存一个
记查询左端点块编号为
查询结果即为
修改的话先还原前缀和,然后修改
读者可以自行探究常数较小的写法
1.2 单点修改,区间最值
沿用上一题的思路,先按
那我们现在需要维护一个什么东西?我们采用抽象思维,等价于维护一个长为
只要会做这个我们直接沿用在整块和散块上就好了。
我们发现有一个东西叫 ST 表,但是在我们印象中这个东西貌似不支持修改……吗?
你分析以下复杂度,你对
但是有更简单的分析方式,你考虑长度为
注意到同机房大手子们还成功胡出了对于每个块重构时用四毛子直接重构,还有什么
1.3 单点修改,区间半群
区间半群没有什么良好的性质,没法建出 ST 表。
你还是和上面一样做,最后还是要维护一个长为
诶呀,你发现我们上面提出一个子问题恰好是原命题的
由此,我们需要知道
实际上还可以用 Sqrt Tree 相关理论优化查询复杂度,但是没有意义(在信奥条件下
2. 单点修改 O(1) ,区间查询 O(\sqrt n)
貌似比较神秘。
2.1 单点加,区间和
对于每个块维护
然后区间查询直接扫一遍每个块,再把散块加上就好了。
2.2 单点加正数,区间最大值
你考虑一个区间的正数只会变大。
那么维护一个
查询还是扫一遍每个整块,再对每个散块取最大值。
2.3 单点改为小于最小值的数,区间最大值
考虑每个块全部开一个单调队列,队首即为最大值,因为每次越改越小,所以直接插入到队尾就做完了。
2.4 单点改,区间最大值
其实是为了这醋包的饺子。
考虑单点修改可以理解成删除一个位置,然后插入一个数。
先光速做掉散块,这一部分是简单的。
考虑我全程没有说强制在线,所以是离线的。
转化一下题意,即有
首先对于每一个块做出块内最大值,然后删除什么的你开一个链表状物,每次删除直接删,你这样直接就是
然后加入一个数直接塞到这个数组的末尾,称这些数为散点。
当散点个数不超过
你遇到了一个问题,在新构成的块中是有下标限制的,相当于你还要
其实可做,你首先在块内使用基数排序,这个排序按下标来排,然后进行诡异多层分块,每层分块都排序,然后维护一个懒标记删除,查询时再删。
查询就先访问每个散点,直接二分每一个块的区间,然后做多层分块找最大值这个操作,为优化二分复杂度,我们采用分散层叠。
已经很难分析复杂度了,大概是
然后我们进行更加抽象的操作,考虑改我们的询问分块为多层分块,可以做到
可能讲的不太清楚,大家可以学习这篇文章。
3. 非常规类型
3.1 区间加,区间和
考虑如何用树状数组来做区间加,区间和。
你发现可以通过维护差分数组
欸,那这样不就转化成了单点修改,前缀和吗?
套用 1.1 和 2.1 的算法可以做到
3.2 树链加,子树和
与 3.1 一样,我们考虑维护
众所周知子树和拍成欧拉序可以转化为 1.1 或 2.1。
3.3 单点改 O(1) ,全局 k 小 O(\sqrt n)
直接对整个数组做一次值域分块,然后你考虑你需要在分块上实现线段树二分。
于是考虑从小到大枚举每一个块,如果这个块内的值加上前面的值还是小于
3.4 单点改 O(\sqrt n) ,全局 k 小 O(1)
考虑这就是维护一个排好序的数组,直接使用分块块状物维护。因为单点修改反而有良好的性质,即一共有
于是每个块开一个长为严格
这一段是我现胡的,如果有问题欢迎骂死我。
3.5 单点加,矩阵和
注意,给定的关键点集合需要是一个排列。
考虑分出
然后你就使用拼好块手法,一块一块的拼起来,如图:
观测到所有颜色的块数量都是
对于最旁边紫色的散块,这其中只有
所以
4. 例题
| 章节 | 练习题 |
|---|---|
| 1.1 | P9212 P10081 |
| 1.2 | P11750 |
| 1.3 | |
| 2.1 | P10081 P6783 |
| 2.2 | |
| 2.3 | P12410 |
| 2.4 | |
| 3.1 | |
| 3.2 | P12536 |
| 3.3 | P4119 P3380 |
| 3.4 | |
| 3.5 | P9987 P7448 P8530 |
尾声
愿根号救赎你。