|
板凳
楼主 |
发表于 2020-2-20 10:43:15
|
只看该作者
基本概念:
设一个长度为N的序列,块的大小为S,从序列的第一个元素起,每S个元素被分为一块,若最终剩余的元素不足S个,令他们组成一块。一般来说存在两种操作,区间求和、区间加法。
当然在很多问题中使用传统数据结构会更加优秀,但是当所需要的信息无法快速合并,就只能使用分块。比如询问一个区间的众数。
加速原理:把数组分成若干个块,通过预处理的方式获得块的某些信息,在对块进行操作的时候直接查询即可无需遍历
但是要注意的是:树状数组>线段树>块状数组(分块)
树状数组:代码简单、常数小(有些时候真的会卡常)
线段树:代码复杂、功能强大、常数大
块状数组:代码复杂、常数大、能维护一些很难快速合并的数据
1.区间求和:
假设询问的区间是 [l,r] ,l所在的块为 bl ,r所在的块为 br
a.当给定区间在同一个块内,即bl=br时
直接枚举 [l,r] 的答案时间 O(S)
b.当给定区间不在同一个块里,即bl<br
那么区间就可以被分为三个部分
(1)[l,块bl的右端点]
(2)块[bl+1~br-1] 显然,当bl和br相邻时,这个部分将不存在
(3)[块br的右端点,r]
对于(1)(3)还是直接枚举计算,对于(2)每个块的 预处理 块内元素和sum,枚举计算。时间复杂度 O(N/S)
2.区间加法:
a.给定区间在同一个块内
直接枚举修改每个元素值,同时更新块bl的sum,时间 复杂度O(S)
b.给定区间不在同一个块内
同上,区间被分为3个部分,且在同一个区间内(1)(3)直接枚举修改
对于(2)每个块不采取遍历的方式,而是维护两个值add(块内每个元素共同累加的数字)和sum。时间复杂度 O(N/S+S) ,显然当S=sqrt(N)时时间复杂度为最小 O(sqrt(N))
例题与代码实现:
基本概念中所阐述的逻辑是较为简单的,但是依旧是 太菜 无法用代码来实现。在学习很多算法的时候都是这样的,其背后的原因就是没有讲具体实现方法,即预处理如何处理。
例题:给定序列an,编号1~n,求a{j}-a{i}的最大值(1<=i<=j<=n)
作者:爱的魔力转圈圈
链接:https://www.acwing.com/blog/content/142/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 |
|