树状数组求区间最大值
来源:互联网 发布:黑客网站源码 编辑:程序博客网 时间:2024/05/16 12:21
讲这个的博文已经不少了,但感觉不够详细不够通俗易懂,所以我尝试着更详细更通俗易懂的说一下我的理解。
这个算法只支持单点修改和区间查询最值。每一次维护和查询的时间复杂度都是O((logn)^2),但这是满打满算的时间复杂度。
假设是要维护和查询区间的最大值(最小值将max改成min 就好了)
这个算法和树状数组维护和查询区间和的方法很相似:
一、数组的含义
1、在维护和查询区间和的算法中,h[x]中储存的是[x,x-lowbit(x)+1]中每个数的和,
2、在求区间最值的算法中,h[x]储存的是[x,x-lowbit(x)+1]中没个数的最大值。
求区间最值的算法中还有一个a[i]数组,表示第i个数是多少。
(其中lowbit(x) = x & (-x) 这个学过树状数组的应该都知道吧。。。。。)
二、单点修改后的更新
1、在维护区间和的算法中,是这样维护单点修改的
2、在来看维护区间最大值的算法,我们先看一整段区间[1,n]都需要初始化的情况。(即 h[] 数组都为0,现在需要用 a[] 数组更新 h[] 数组)
这样是可行,于是我们就有了一个O(n*logn)的维护方法,即当要更新一个数的时候,把 h[] 数组清零, 然后用数组 a[] 去更新 h[] 数组。
但这个复杂度显然太高了。
可以发现:对于x,可以转移到x的只有,x-2^0,x-2^1,x-2^2,.......,x-2^k (k满足2^k < lowbit(x)且2^(k+1)>=lowbit(x))
举例:
若 x = 1010000
= 1001000 + lowbit(1001000) = 1001000 + 1000 = 1001000 + 2^3
= 1001100 + lowbit(1001100) = 1001100 + 100 = 1001100 + 2^2
= 1001110 + lowbit(1001110) = 1001110 + 10 = 1001110 + 2^1
= 1001111 + lowbit(1001111) = 1001111 + 1 = 1001111 + 2^0
所以对于每一个h[i],在保证h[1...i-1]都正确的前提下,要重新计算h[i]值的时间复杂度是O(logn),具体方法如下:
这样,我们就可以得到一个和树状数组维护区间合算法很像的算法
这个算法的时间复杂度是O((logn)^2),所以现在就可以在O((logn)^2)的时间内完成最值的区间维护了。
三、区间查询
1、树状数组求区间合的算法是这样子的:
2、树状数组求区间最大值:
直接照搬求区间合的方法显然是不行的。
因为区间合中,要查询[x,y]的区间合,是求出[1,x-1]的合与[1,y]的合,然后相减就得出了[x,y]区间的合。
而区间最值是没有这个性质的,所以只能够换一个思路。
设query(x,y),表示[x,y]区间的最大值
因为h[y]表示的是[y,y-lowbit(y)+1]的最大值。
所以,可以这样求解:
若y-lowbit(y) > x ,则query(x,y) = max( h[y] , query(x, y-lowbit(y)) );
若y-lowbit(y) <=x,则query(x,y) = max( a[y] , query(x, y-1);
这个递归求解是可以求出解的,且可以证明这样求解的时间复杂度是O((logn)^2)
具体代码:
时间复杂度的证明:(换成二进制来看)
因为y经过Logn次变换以后,其与x不同的最高位至少下降了1位,所以最多进行(logn)^2次变换
举例:
y = 1010000
x = 1000001
1010000
=> 1001111 => 1001110 =>1001100 =>1001000
=>1000111 => 1000110 => 1000100
=> 1000011 = > 1000010
=>1000001
=>1000000 < 1000001
最后贴上我hdu1754的代码,这一题就是一道单点修改和区间查询最大值的题。
- 树状数组求区间最大值
- 树状数组求区间最大值
- 树状数组求区间最大值一类问题
- 树状数组求区间最大值(树状数组)(复习)
- I Hate It(树状数组--区间求最大值)
- 树状数组写区间最大值
- 树状数组维护区间最大值
- 树状数组求区间和
- 树状数组求区间极值
- 树状数组求区间极值
- 树状数组求区间和
- HDOJ 题目1754 I Hate It(树状数组,单点更新,求区间最大值)
- 树状数组求区间最值(转载)
- 树状数组求区间最值
- 树状数组--改区间求点
- 用树状数组求区间最值
- 树状数组求区间最值
- 树状数组求序列的区间和
- Java通过反射创建对象
- 高级装配 —— 如何在运行时计算要注入到 bean 属性中的值?
- spring boot整合quartz
- MySQL索引优化
- Regsvr32和Regasm注册DLL COM组件
- 树状数组求区间最大值
- .NET Framework 字符串相关操作细节介绍
- 红黑树性质和定义
- 框架学习之hibernate-02实体与实体之间的关系
- fudannlp初试
- if判断对象是否为空
- win 10+outlook2013最小化隐藏
- jquery获取动态生成的元素
- 详解spl_autoload_register()函数