对《挑战程序设计竞赛》的一个记录
第三章 出类拔萃——中级篇
3.3活用各种数据结构——RMQ/树状数组/分桶法和平方分割
RMQ(区间最值查询)
有一个长度为n的乱序序列,要求求出区间[L,R]内的最大值或最小值(或者有多次询问发生)
(1)普通解法:每次询问遍历一遍数组(效率低,n很小时,可以考虑一下)
(2)ST算法:具体看之前写过的这篇,ST算法可以进行O(1)的查询,但是不能维护值得更改,适合用在需要大量询问,但是不改变值得情况下。
(3)线段树:可以看线段树篇内的习题
(4)树状数组:树状数组见下面详解
用树状数组求区间[L,R]最值时,如果待查区域在[L,R]范围内,则去该区域最值,否则,只取当前位置的数据,索引后减1并重复上述步骤,直至全部查询完
int getMax(int r,int l)
{
int ans = val[r];
while(l <= r)
{
ans = max(ans,val[r]);
for(--r; r - l >= lower_bit(r);r -= lower_bit(r))
{
ans = max(ans,cnt[r]);
}
}
return ans;
}
(5)平方分割:见下面详解
(6)。。。待补充
树状数组
经常用到YB学长的这份自己整理的资料,觉得挺好,直接贴上来记录一下(侵删,勿转载)
单一更新区间查询
树状数组的原英文表达:Binary Indexed Tree(BIT),直译的意思便是:二进制标记树。这提示我们,树状数组这种数据结构的原理是二进制数。
如果数组A是基础数组,数组C是区间数组。那么,在具体介绍数组C的特点前,先给出如下的树状关系图:
仔细观察上图,容易发现:
数组C[]分别代表的区间为:
C1=A1 [1,1]
C2=C1+A2=A1+A2 [1,2]
C3=A3 [3,3]
C4=C2+C3+A4=A1+A2+A3+A4 [1,4]
C5=A5 [5,5]
C6=C5+A6=A5+A6 [5,6]
C7=A7 [7,7]
C8=C4+C6+C7+A8=A1+A2+A3+A4+A5+A6+A7+A8 [1,8]
C9=A9 [9,9]
也就是说,每个数组Ci,至少包含Ai,同时包含所有满足j+lowest_bit(j)=i的Cj数组。例如C8不仅包含A8,同时还包含了C4,C6,C7。而
410=1002,1002+1002=10002=810
610=1102,1102+