分块和树状数组的巧妙结合

小柯

2020-03-02 13:31:24

Personal

# 背景 某天,$xk$ 正在学习树状数组。此时,老师正在讲分块,用以过渡到树状数组。 放上$ppt$: ![](https://s2.ax1x.com/2020/03/02/3RYxEQ.png) 然后,老师就开始讲树状数组了...... # 故事 某天 $xk$ 正在睡觉, $Ta$ 正在思考区间查询和修改的最优复杂度。$Ta$ 想到了常用的三种数据结构:分块、树状数组和线段树。$Ta$ 回想起学树状数组时,~~是多么的美好~~老师分块的方法。这样的方法中对于每个块都是有前缀和在维护的,而暴力修改也是针对前缀和进行暴力,那为什么不把这个前缀和替换为树状数组呢? > $\tiny\texttt{注:这里暂时特指单点修改和区间查询。}$ 这样~~淦(可恶的输入法)~~ 干,就可以将块内的暴力时间缩减为 $O(log{\sqrt{n}})$ ,也许你会问那对于询问外面的块的时候还不是需要 $O(\sqrt{n})$ 的复杂度? 顺着刚刚的思路,每个块累加的暴力,不也正可以用树状数组来优化吗?这样下来,每个块的暴力,就也变成了$O(log{\sqrt{n}})$的复杂度。 总结一下, $xk$ 这天晚上想到的就是$\color{red}\huge\texttt{分块套树状数组}$。 至此,故事讲完了~~请勿吐槽啥情节都没有~~。 # 思考 既然可以做到 $O(log{\sqrt{n}})$ 的单点修改和区间查询,那么该如何支持区间修改和区间查询呢? ### $way$ $1$ 仍然利用刚刚的 $\color{red}\small\texttt{分块套树状数组}$ 可不可以呢?答案是肯定的。利用容斥原理和两个这样的数据结构就可以做到。具体做法可以类比树状数组,这里不再赘述,如果不清楚的还可以看看这张$ppt$(这是树状数组的): ![](https://ae01.alicdn.com/kf/H7336a79bf9e545359e894113de3942c4y.png) ### $way$ $2$ 既然树状数组可以套,那线段树嘞?当然也是可以的啦。但是需要注意的一点是,$\texttt{分块的常数*线段树的常数=巨大的常数}$,~~然后就没有然后了~~。 # $\small\texttt{但是请注意}$ 你以为你学到了一个非常高深而高效的东西? 对不起: $$O(log{\sqrt{n}})=O(log{n^{\frac{1}{2}}})=O(\frac{log{n}}{2})\approx O(log{n})$$ 具体一点,用人话来讲就是$\tiny\texttt{这篇文章啥用没有。}$ ~~请不要打我~~。 ~~请留下一个赞再走吧/xyx~~。