线段树及其应用.ppt
《线段树及其应用.ppt》由会员分享,可在线阅读,更多相关《线段树及其应用.ppt(59页珍藏版)》请在三一办公上搜索。
1、线段树及其应用,江苏省华罗庚中学 xxx,为什么要用线段树?,例1:有M个数排成一列,初始值全为0,然后做N次操作,每次我们可以进行如下操作:(1)将指定区间的每个数加上一个值;(2)将指定区间的所有数置成一个值;(3)询问一个区间上的最小值、最大值、所有数的和。,为什么要用线段树?,一般的模拟算法:用一张线性表表示整个数列,每次执行前两个操作的时候,将对应区间里的数值逐一进行修改,执行第三个操作的时候,线性扫描询问区间,求出三个统计值,每次维护的时间复杂度O(m),整体的时间复杂度O(mn)。,为什么要用线段树?,readln(m,n);for i:=1 to n dobegin read(
2、t);if t=1/指定区间加上一个值 then begin readln(left,right,x);for j:=left to right do aj:=aj+x;end;,if t=2/指定区间置成一个值then begin readln(left,right,x);for j:=left to right do aj:=x;end;,为什么要用线段树?,if t=3/询问一个区间的最小值、最大值、和then begin readln(left,right);min:=aleft;max:=aleft;sum:=aleft;for j:=left+1 to right do begin
3、 if ajmax then max:=aj;sum:=sum+aj;end;writeln(min,max,sum);end;,为什么要用线段树?,机器配置:Pentium 1.3G 512M,时间复杂度是线性的!,为什么要用线段树?,当m、n的值比较大时,这个算法就太低效了。其低效的原因主要是我们在每一次操作中都是针对每个元素进行维护的,而这里我们进行的操作都是针对一个区间进行操作的。假如设计一种数据结构,能够直接维护所需处理的区间,那么就能更加有效地解决这个问题。,线段树(区间树),线段树的结构,定义1:长度为1的线段称为元线段。定义2:一棵树被称为线段树,当且仅当这棵树满足如下条件:(
4、1)该树是一棵二叉树;(2)树中的每一个结点都对应一条线段a,b;(3)树中的结点是叶子结点,当且仅当它所代表的线段是元线段;(4)树中非叶子结点都有左右两棵子树,左子树树根对应线段a,(a+b)/2,右子树树根对应线段(a+b)/2,b。,线段树的结构,如T(1,10)的结构:,线段树的结构,常用的是需要对数列进行处理,将区间a,b分解为a,(a+b)/2,(a+b)/2+1,b,当a=b时表示为一个叶子结点,表示数列中的一个数。,线段树的性质,性质1:长度范围为1,L的一棵线段树的深度不超过log2(L-1)+1;性质2:线段树上的结点个数不超过2L个;性质3:线段树把区间上的任意一条线段
5、都分成不超过2log2L条线段。,线段树的存储方式,(1)链表实现:Node=TNode;TNode=record Left,Right:integer;LeftChild,RightChild:Node;end;(2)数组模拟链表:Left,Right,LeftChild,RightChild:array1.n of integer;(3)堆的结构:根节点为1,对于结点x,其左孩子为2x,右孩子为2x+1,线段树的基本操作及实现,线段树的构造procedure build(cur:Node;l,r:integer);begin cur.Left:=l;cur.Right:=r;if l=r
6、then begin cur.LeftChild:=nil;cur.RightChild:=nil;end else begin new(cur.LeftChild);new(cur.RightChild);build(cur.LeftChild,l,(l+r)div 2);build(cur.RightChild,(l+r)div 2+1,r);end;end;,线段树的基本操作及实现,线段树的查询procedure query(cur:Node;l,r:integer);var LC,RC:Node;begin LC:=cur.LeftChild;RC:=cur.RightChild;if
7、(l(cur.Left+cur.Right)div 2 then query(RC,l,r);end;end;,线段树的维护方法,对区间进行修改,对元素进行修改,设置为同一个数,统一加上一个数,修改,查询,区间的和,区间的最大值,区间的最小值,其它,线段树的维护方法,如果想要让线段树发挥实际的作用,必须在每个结点上维护额外的域来记录更多的信息。首先看一个引例的弱化版,假设每次修改操作只能对其中某个元素进行修改。在每个结点上额外维护3个域:max、min、sum,分别表示子树上的最大值、最小值和所有元素的和。,(1)对元素进行修改,procedure insert(cur:Node;x,num:
8、integer);var LC,RC:Node;begin LC:=cur.LeftChild;RC:=cur.RightChild;if cur.Left=cur.Right/对叶结点的处理 then begin cur.Min:=num;cur.Max:=num;cur.Sum:=num;end else begin if x(cur.Left+cur.Right)div 2 then insert(RC,x,num);cur.Sum:=LC.Sum+RC.Sum;/上推 if(LC.MaxRC.Max)then cur.Max:=LC.Max else cur.Max:=RC.Max;i
9、f(LC.MinRC.Min)then cur.Min:=LC.Min else cur.Min:=RC.Min;end;end;,(2)对区间进行查询,function querysum(cur:Node;l,r:integer):integer;var LC,RC:Node;ret:integer;begin LC:=cur.LeftChild;RC:=cur.RightChild;ret:=0;if(l(cur.Left+cur.Right)div 2 then ret:=ret+querysum(RC,l,r);end;querysum:=ret;end;,(3)对区间修改(统一加上一
10、个数),procedure update(cur:Node;l,r,delta:integer);var LC,RC:Node;/需要给每个区间增加一个变量deltabegin LC:=cur.LeftChild;RC:=cur.RightChild;if(l(cur.Left+cur.Right)div 2 then update(RC,l,r,delta);cur.Sum:=LC.Sum+LC.Delta*(LC.Right-LC.Left+1);cur.Sum:=cur.Sum+RC.Sum+/上推 RC.Delta*(RC.Right-RC.Left+1);end;end;,(4)对区
11、间查询,function querysum(cur:Node;l,r:integer):integer;var LC,RC:Node;ret:integer;begin LC:=cur.LeftChild;RC:=cur.RightChild;ret:=0;if(l(cur.Left+cur.Right)div 2 then ret:=ret+querysum(RC,l,r);end;querysum:=ret;end;,(5)对区间修改(设置为同一个数),procedure update(cur:Node;l,r,num:integer);var LC,RC:Node;begin LC:=c
12、ur.LeftChild;RC:=cur.RightChild;if cur.En/如果该区间已经是同一个值,将值下传给左右区间 then begin cur.sum:=(cur.right-cur.left+1)*cur.data;if LCnil then begin LC.Data:=cur.Data;LC.En:=true;end;if RCnil then begin RC.Data:=cur.Data;RC.En:=true;end;cur.En:=false;end;if(l(cur.Left+cur.Right)div 2 then update(RC,l,r,num);cur
13、.Sum:=calcsum(LC)+calcsum(RC);end;end;,function calcsum(cur:Node):integer;begin if cur.En then calcsum:=(cur.Right-cur.Left+1)*cur.Data else calcsum:=cur.Sum;end;,(6)对区间查询,function querysum(cur:Node;l,r:integer):integer;var LC,RC:Node;ret:integer;begin LC:=cur.LeftChild;RC:=cur.RightChild;ret:=0;if(
14、l(cur.Left+cur.Right)div 2 then ret:=ret+querysum(RC,l,r);end;querysum:=ret;end;,线段树的维护方法,线段树上的参数通常有两种维护方法:(1)一类参数表达了结点的性质,通常具有树型的递推性质,可以从下向上进行递推计算;(如sum,max,min)(2)一类参数表达了子树的性质,维护的时候可以先打上标记,在需要进一步访问其子结点的时候从上向下传递。(如delta,en),线段树的维护方法,线段树上维护或者询问过程的一般过程:对于当前区间l,rif 达到某种边界条件(如叶结点或被整个区间完全包含)then 对维护或是询问
15、作相应处理else 将第二类标记传递下去(注意,在查询过程中也要处理)根据区间的关系,对两个孩子结点递归处理 利用递推关系,根据孩子结点的情况维护第一类信息,为什么要用线段树?,应用举例,例2、线段覆盖 在所有不大于30000的自然数范围内讨论一个问题:已知n条线段,把端点依次输入告诉你,然后有m(30000)个询问,每个询问输入一个点,要求这个点在多少条线段上出现过。,n=4 m=3线段:0,3 4,6 2,6 5,7询问:1,3,5,应用举例(线段覆盖),可以直接对问题处理的区间建立线段树,在线段树上维护区间被覆盖的次数。将n条线段插入线段树,然后对于询问的每个点,直接查询被覆盖的次数即可
16、。,应用举例(线段覆盖),这道题目完全可以不用线段树,将每个线段拆分成(L,+1),(R+1,-1)的两个事件点,每个询问点也在对应坐标处加上一个询问的事件点,排序之后扫描就可以完成题目的询问。,Sum 1 1 2 2 2 3 3 1 0,+1,-1,-1,-1,+1,+1,+1,-1,应用举例(线段覆盖),因为此问题是一个离线的问题,这是一个很简单的离线算法。线段树在处理在线问题的时候会更加有效,因为它维护了一个实时的信息。,应用举例,例3、售票系统 某次列车途经C个城市,城市编号依次为1到C,列车上共有S个座位,每一个售票申请包含三个参数,分别用O、D、N表示,O为起始站,D为目的地站,N
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 线段 及其 应用
链接地址:https://www.31ppt.com/p-6230394.html