为了更好的理解线段树,还是从基本概念说起吧。记得张昆伟大牛曾说,线段树其实最初来自计算几何。。赞先不管它的来历,我们来看看它能干什么?线段树可以在O(logn)时间内修改某个点,同时(记住是同时,因为其他数据结构可以再O(1)时间内修改某个点)在O(logn)内查询某区间的最大(小)值,或者元素和。所以线段树适合需要频繁更新和查询的一种数据结构。一般来说,线段树的应用分为单点更新,区间查询,区间修改,区间合并,扫描线。。
所以这篇博客利用一些例题来讲解线段及其应用。
(1)单点更新,区间查询(这是线段最简单的应用, 代码也非常简单)
uva 12299 RMQ with shifts http://acm.uva.es/local/online_judge/search_uva.html
1,只有两个操作,查询(l, r)的最小值
2,循环移动(i1, i2, ...in)里面的元素,比如a[i1] 变为a[i2]...a[ij] = a[i(j+1)] ...a[i(n)] = a[i1],这里因为给的数据量非常小,所以我们需要对里面每个元素进行单点更新就好啦
所以非常好写,理解后分分中的事。
hdu 1754 裸题
hdu 2795 线段树,注意刚看到区间范围时可能会觉得无从下手,因为是训练题,挂的是单点跟新,于是在想想看到询问次数才200000,所以对于以后的是没有的范围,贴海报用不了这么多空间,于是题目就简单了,维护区间最大值就可以。
(2 )区间更新+懒标记
(3)区间合并+区间查询+懒标记
区间合并一般用来维护一段最长连续序列的,虽然有时候写起来跟(2)并没有很大区别。但是如果维护最长连续串时,要注意合并时,父节点的最长连续序列可能是左右子树中连续序列的最大值,也可能是横跨左右子树,所以才出现所谓的区间合并。本质上没有很大区别。
hdu 3199 acm.hdu.edu.cn/showproblem.php?pid=3911
此题就是维护最长的连续黑白块,最要注意的是区间查询时,要注意两点:
1:可能最长串时横跨左右子树的。
2:最长串不能超过查询区间的长度。
在杭电上交即使用输入输出外挂,速度还是很慢,贴代码出来希望大家能给点意见,看哪里还可以优化。
代码移步到:http://blog.csdn.net/robotcator/article/details/38541935
(4) 离散化+扫描线
一般离散化x坐标或者y坐标(离散化的原因是数据量很小,但是数据的范围很大,都是零星的分布,所以零散化后节约空间和时间),然后用y或者x的扫描线从小到大扫描一遍,然后更新线段树保存的信息。。
hdu 4007 Dove http://acm.hdu.edu.cn/showproblem.php?pid=4007(包含边界)
poj 2482 http://poj.org/problem?id=2482(优美的情书)这个不包含边界
poj2482可是错了我一地啊,runtime error知道写4007时才发现错误,交上去过了。。。=。=
(5) 莫队算法
(5) 曼哈顿生成树
(6) 莫对算法
貌似只是处理离线问题.其他还不懂,主要是曼哈顿生成树还是不会写=。=所以先修课为曼哈顿生成树
(6)二维线段树
(7) 二维线段树