zkw线段树讲稿统计的力量线段树
『zkw线段树及其简单运用』
『zkw 线段树及其简单运⽤』<更新提⽰><第⼀次更新>阅读本⽂前,请确保已经阅读并理解了如下两篇⽂章:<正⽂>引⼊这是⼀种由THU −zkw ⼤佬发明的数据结构,本质上是经典的线段树区间划分思想,采⽤了⾃底向上的⽅式传递区间信息,避免的递归结构,其代码相对经典线段树更简单,常数更⼩,易于实现。
统计的⼒量-源⾃。
基础⾮递归接下来,我们将讲解zkw 线段树的第⼀种实现形式,⽤于单点修改 区间查询,我们以查询区间最⼤值为例来讲解。
建树普通线段树需要建树,zkw 线段树当然也需要建树。
考虑线段树的⼀个性质,其树上的叶节点代表的往往都是形如[x ,x ]的元区间,⽽且除最后⼀层外,线段树是⼀颗满⼆叉树,所以我们要把这颗线段树的数组⼤⼩先申请好了。
⼀棵满⼆叉树有x 个节点时,它有x +12个叶⼦节点,⽽我们需要⾄少n 个叶⼦节点的线段树,即使x +12≥n ,那么我们设x =1,在x +12<n 时不断执⾏x ∗=2,就能得到⾜够⼤⼩的线段树下标base ,由于线段树的叶⼦节点可能分布在两层,所以保险起见,我们还需再将x 扩⼤⼀倍,即在x +1<n 时不断执⾏x ∗=2就可以了。
得到合适的下标位置后,将1−n 下标位置的原数据直接存⼊线段树的叶⼦节点即可。
其实,我们还需将下标再扩⼤两个位置,即需要保证x >n ,才停⽌执⾏x ∗=2。
其原因是这样的:在执⾏区间查询操作时,我们需要将查询区间[l ,r ]更改为(l ,r )(关于原因,我们之后再分析),才便于zkw 线段树的查询,那么在询问[1,n ]时,可能为调⽤到[0,n +1]的原下标,所以还需再扩⼤两个位置。
得到了合适的下标base 并将1−n 的数据存⼊对应位置后,当然我们还要对1到base −1的线段树位置进⾏区间更新,这个普通的更新就可以了。
Code :单点修改直接在叶节点上修改对应的值,然后更新其每⼀个⽗节点即可。
统计的力量-线段树
清华大学 张昆玮
6
2019年10月17日
*计算几何在长期的发展中,
诞生了许多实用的数据结构。
*区间查询,穿刺查询都是计算几何解决的问题 *作为特例中的特例,线段树解决的问题是:
* 一维空间上的几何统计
*高维推广(kd-tree & …)可以进行正交查询
*由于竞赛中涉及计算几何的内容有限,不展开
*计算几何!
2019年10月17日
*for(T[n+=M]=V, n>>=1;n;n>>=1)
* T[n]=T[n+n]+T[n+n+1];
*没了? *没了。
清华大学 张昆玮
*C语言更简单
35
2019年10月17日
*仅使用了两倍原数组的空间 *其中还完整地包括了原数组 *构造容易:
* For i=M-1 downto 1 do T[i]=T[2i]+T[2i+1];
44
2019年10月17日
*标记的传递与收集
懒惰即美德。
清华大学 张昆玮
45
2019年10月17日
清华大学 张昆玮
*区间修改
噩梦的开始
46
2019年10月17日
*RMQ (Range Minimum Query) *区间最小值查询 *线段树 *支持区间修改:
* 某一区间的数值全部增加一个可正可负的数
2019年10月17日
*这不就和树状数组一样了? *本来就应该一样。
*回过头说,树状数组究竟是什么? *就是省掉一半空间后的线段树加上中序遍历 *计算位置需要lowbit什么的 *我们用的是先序遍历,符合人的思考习惯。
线段树
对于线段树中的每个结点, 其表示一个区间,我们可以记录和这个区间相关 的一些信息(如最大值、最小值、和等) ,但要满足可二分性,即能直接由其子
结点的相关信息得到。 对于询问区间信息和修改区间信息的操作,线段树一般在能 O(log n) 的时间 内完成,而且常数相对较小(和后面的伸展树比较) ,算是一种高效实用的数据 结构。 (2)线段树的基本操作——查询区间信息 使用线段树的目的就是能高效地查找和修改区间信息, 下面先介绍第一个操 作——查询操作。 对于当前要查询的区间 a, b ,我们从线段树的根结点开始,如果当前结点 表示的区间被查询区间完全包含,那么更新结果,否则分别考察左右子结点,如 果查询区间与某个子结点有交集(也可能两个都有) ,那么就递归考察这个子结 点。代码框架如下1:
对于任意一个区间,会被划分成很多在线段树上存在的区间,可以证明,划 分出来的区间在线段树的每层最多有两个,又因为线段树的深度为 O(log n) ,因 此查询操作的时间复杂度为 O(log n) 。
(3)线段树的基本操作——修改区间信息 相对于查询区间信息,修改区间信息显得稍微复杂一些。
1
本文中的代码均使用 C++语言描述
(4)线段树特点总结 利用线段树, 我们可以高效地询问和修改一个数列中某个区间的信息,并且 代码也不算特别复杂。 但是线段树也是有一定的局限性的, 其中最明显的就是数列中数的个数必须 固定,即不能添加或删除数列中的数。对于这个问题,下面介绍的伸展树就可以 完美的解决。
(7,10]
(0,1] (1,2] (2,3] (3,5] (5,6]
(6,7] (7,8]
(8,10]
(3,4]
线段树_树状数组I(11页建树有修正)
如果原数组从a[1]~a[n],调用build(1,1,n)即可
12
• 更新某个点的数值,并维护相关点的信息
线段树——代码实现(更新)
void update(int id,int pos,int val) { if (tree[id].left==tree[id].right) { tree[id].sum=tree[id].max=val; } else { int mid=(tree[id].left+tree[id].right)/2; if (pos<=mid) update(id*2,pos,val); else update(id*2+1,pos,val); tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; tree[id].max=max(tree[id*2].max,tree[id*2+1].max) } }
5
线段树——结构
• 线段树的本质是一棵二叉树,丌同亍其它二叉树, 线段树的每一个节点记录的是一段区间的信息。 • e.g. 对亍长度为5的数组a[1]~a[5]
[1,5] [1,3] [4,5] 对于任一非叶子节点, 若该区间为[L,R],则 左儿子为[L,(L+R)/2] 右儿子为[(L+R)/2+1,R]
23
树状数组——总结
1、树状数组可以更新点查询区间,也可以更新区间 查询点,但一般不能更新区间查询区间。 2、单操作时间复杂度O(log2N),空间复杂度O(N). 3、代码简洁。 思考:1、如何实现树状数组更新区间查询点?(例如 给某个区间统一加一个数,询问某点当前值) 2、修改tree数组的定义,使其能够实现更新 某个点的值,并询问[1,pos]中的最大值。
HH神总结的线段树专辑_超经典的
46
scanf("%d",&x[i]);
47
sum += query(x[i] , n - 1 , 0 , n - 1 , 1);
48
update(x[i] , 0 , n - 1 , 1);
49
}
50
int ret = sum;
51
for (int i = 0 ; i < n ; i ++) {
52
53 1));
54
else if (op[0] == 'S') update(a , -b , 1 , n , 1);
55
else update(a , b , 1 , n , 1);
56
}
57
}
58
return 0;
}
o hdu1754 I Hate It 题意:O(-1) 思路:O(-1) 线段树功能:update:单点替换 query:区间最值 ?View Code CPP
37
if (R > m) ret += query(L , R , rson);
38
return ret;
39 }
40 int main() {
41
int T , n;
42
scanf("%d",&T);
43
for (int cas = 1 ; cas <= T ; cas ++) {
44
printf("Case %d:\n",cas);
在代码前先介绍一些我的线段树风格:
maxn 是题目给的最大区间,而节点数要开 4 倍,确切的来说节点数要开大于 maxn 的最小 2x 的两倍
(精品教案)《统计》讲课稿范文(通用5篇)
(精品教案)《统计》讲课稿范文(通用5篇)《统计》讲课稿范文(通用5篇)作为一名教学工作者,总归要编写讲课稿,借助讲课稿能够有效提升自个儿的教学能力。
优秀的讲课稿都具备一些啥特点呢?下面是小编收集整理的《统计》讲课稿范文(通用5篇),仅供参考,希翼可以帮助到大伙儿。
【教材分析】《统计》是义务教育课程标准实验教科书数学(人教版)下册第9单元的内容。
原教材上是一幅教师带领学生举行实地观看、统计的插图。
关于没有条件、别能实地统计的学校,这部分内容又该如何上呢?我将教材中的盆花变成纸花,一排一排钉在黑板上,便于学生数数、统计。
巩固练习中,原教材是让学生统计全班每人的生日。
但关于农村小学低年级的儿童来讲,大多数学生全然记别得自个儿的生日。
所以,我设计了几份统计表供学生举行练习。
【学生分析】全班54名学生。
学生的思维比较活跃,有一定合作交流学习的能力。
教师所要做的算是设计、组织学生举行有价值的统计活动。
【教学目标】1、初步体验数据的收集、整理、描述和分析过程,会用简单的办法收集整理数据。
2、初步认识条形统计图和简单的统计表;能依照统计表中的数据提出并回答简单的咨询题。
3、培养合作意识。
【教学流程】一、激趣、引入、感知。
师:小朋友,今天我们竞赛一下,看哪组同学表现得最好,老师将送给他们红五星。
你们看,(出示各XXX花)有一位一年级的小朋友在学校各方面的表现都别错,得到了那么多的花!这些花美丽吗?这些花有几种颜群?讲讲有哪些颜XXX?怎么样才干懂各种颜群的花有几朵?(让学生自个儿想方法。
)师生共同数出红花的朵数。
师:我们刚刚数数的过程算是对数据举行统计。
(板书:统计)师:大伙儿想把各群的花有几朵统计下来吗?老师给大伙儿请来一具好帮手,看例1。
【创设与学生日子实际相同的学习情境,激发了学生的学习积极性。
继续引入课题,朴实自然,也渗透了思想教育。
】二、教学例1。
教师出示条形统计图,并讲明:图中的四根条形柱分不表示下面所列花的朵数。
线段树讲解——精选推荐
线段树讲解浅谈线段树在信息学竞赛中的应⽤岳云涛yyt @ comindeWuhan University【摘要】本⽂介绍了⼀种⾼效的基于分治思想的数据结构——线段树,具体讲解了线段树的建树,查找,删除,统计等基本操作。
并结合了⼀些例题深⼊研究了线段树的基本性质和线段树的应⽤⽅法。
⽂章最后给出了⼀些线段树的练习题⽬。
【关键词】数据结构⼆叉树线段树【⽬录】引⾔ (3)1 线段树 (3)1.1 线段树的基本结构 (3)1.2 线段树的性质 (4)1.3 线段树的基本存储结构和操作 (4)2 线段树的初级应⽤ (9)2.1 例题:City Horizon (9)2.2 例题 Joseph Problem (12)3 线段树的进阶应⽤ (15)3.1 例题 Frequent Values (15)3.2 例题 K-th Number (17)4 线段树的⼀些推⼴应⽤ (17)4.1 多维线段树 (17)4.2 线段树与其他数据结构的组合 (18)5 线段树应⽤总结 (19)6 线段树练习题⽬推荐 (19)【正⽂】引⾔在信息学竞赛中,我们经常会碰到⼀些跟区间有关的问题,⽐如给⼀些区间线段求并区间的长度,或者并区间的个数等等。
这些问题的描述都⾮常简单,但是通常情况下数据范围会⾮常⼤,⽽朴素⽅法的时间复杂度过⾼,导致不能在规定时间内得到问题的解。
这时,我们需要⼀种⾼效的数据结构来处理这样的问题,在本⽂中,我们介绍⼀种基于分治思想的数据结构--线段树。
1 线段树1.1 线段树的基本结构线段树是⼀种⼆叉树形结构,属于平衡树的⼀种。
它将线段区间组织成树形的结构,并⽤每个节点来表⽰⼀条线段。
⼀棵[1,10)的线段树的结构如图 1.1所⽰:图1.1 线段树的结构可以看到,线段树的每个节点表⽰了⼀条前闭后开,即[a,b)的线段,这样表⽰的好处在于,有时候处理的区间并不是连续区间,可能是离散的点,如数组等。
这样就可以⽤[a,a+1)的节点来表⽰⼀个数组的元素,做到连续与离散的统⼀。
文档:线段树及其应用
线段树及其应用常州市教育教研室、常州市第一中学林厚从2009-4-13一、为什么要用线段树例1.有一列数,初始值全部为0。
每次可以进行以下三种操作中的一种:(1)给指定区间的每个数加上一个特定值;(2)将指定区间的所有数置成一个统一的值;(3)询问一个区间上的最小值、最大值、所有数的和。
[问题分析]在最朴素的模拟算法中,通常用线性表存储整个数列,然后在执行这三种操作的过程中,对每个在处理区间或是询问区间中的元素逐一进行处理。
假设这个数列的长度为n,总操作数为m,那么这个算法每次维护的时间复杂度为O(n),整体的时间复杂度为O(mn)。
当m与n比较小的时候,这无疑是一个不错的策略。
但是如果m与n的值比较大,那么这个算法显然就太低效了。
这个算法低效的一个重要原因就是:所有的维护都是针对元素的,而题目中所有的维护都是针对区间的。
所以,我们的优化也就应该从这里着手。
假如我们设计一种数据结构,能够直接维护所需处理的区间,那么就能更加有效地解决这个问题了。
线段树就是这样一种数据结构。
它能够将我们需要处理的区间不相交的分成若干个小区间,每次维护都可以在这样一些分解后的区间上进行,并且查询的时候,我们也能够根据这些被分解了的区间上的信息合并出整个询问区间上的查询结构。
二、线段树的结构定义1:长度为1的线段称为元线段。
定义2:一棵树被称为线段树,当且仅当这棵树满足如下条件:(1)该树是一棵二叉树;(2)树中的每一个结点都对应一条线段[a,b];(3)树中的结点是叶子结点,当且仅当它所代表的线段是元线段;(4)树中非叶子结点都有左右两棵子树,左子树树根对应线段[a ,(a+b)/2],右子树树根对应线段[(a+b)/2,b]。
通俗地说,线段树是一棵二叉树,树中的每一个结点表示了一个区间[a,b]。
每一个叶子结点上a+1=b,这表示了一个初等区间。
对于每一个内部结点b-a>1,设根为[a,b]的线段树为T(a,b),则进一步将此线段树分为左子树T(a,(a+b)/2),以及右子树T((a+b)/2,b),直到分裂为一个初等区间为止。
线段树111 ppt课件
• 这样,修改和询问都可以在O(lgN)时间内解决。 • 最后问题:如何表示线段树,如何建立线段树,
如何初始化线段树。 • 表示:
struct node { int sum, lbound, rbound; node *lchild, *rchild;
}; node pool[N*3], *alloc = pool, *root;
线段树
• 维护伪代码,将Ki修改为X,相当于将[i,i]修改为X
• void Modify( T ) { if ( T左边界 == T右边界 ) { T中元素和 = X //因为T中仅有一个元素 } else { mid = ( T左边界 + T右边界 ) / 2 value = 0 if ( i <= mid ) { value += Modify( T左子结点 ) } if ( i > mid ) { value += Modify( T右子结点 ) } T中元素和 = value }
提示:利用 Si = Si-1 + Ki
区间统计
• 现在增加一些难度: 在m个询问中穿插t个修改,每个修改要 求将某个Ki修改成指定值
• 如果还是用预处理S的方法,那么每次 修改时维护S数组的代价是多少?O(n) 的(你能说出理由吗?)
• 这样t次修改复杂度是O( tn )的,有没有 更好的方法解决这个问题?
线段树111 ppt课件
本讲稿主要来源
南开大学、浙江大学、福建大学
线段树
• 在一类问题中,我们需要经常处理可以 映射在一个坐标轴上的一些固定线段, 例如说映射在OX轴上的线段。由于线段 是可以互相覆盖的,有时需要动态地取 线段的并,例如取得并区间的总长度, 或者并区间的个数等等。一个线段是对 应于一个区间的,因此线段树也可以叫 做区间树。
线段树应用PPT课件
线段树与数组的比较
总结词
线段树在处理复杂查询时优 于数组
详细描述
数组虽然便于随机访问,但 在处理复杂查询如区间最大 值、最小值等问题时,线段 树能够提供更快的查询速度
。
总结词
线段树在处理动态数据集时更具优势
详细描述
当数据集频繁变动时,线段树能够快速地 更新和维护数据,而数组可能需要重新构 建或采取其他复杂的操作。
空间效率
线段树通过节点间的关系,将大 问题分解为小问题,所需空间相 对较小。
线段树的缺点
01
02
03
节点分裂与合并
在线段树进行插入、删除 等操作时,可能会导致节 点分裂或合并,使得树的 平衡性难以维护。
构造与重建
线段树在处理大规模数据 时,可能需要多次重建, 导致时间复杂度较高。
适用场景限制
线段树适用于区间查询问 题,对于其他类型的问题 可能需要其他数据结构或 算法。
线段树应用ppt课件
目录
• 引言 • 线段树的原理 • 线段树的应用实例 • 线段树与其他数据结构的比较 • 线段树的优缺点分析 • 总结与展望
01 引言
什么是线段树
定义
线段树是一种用于处理区间查询问题 的数据结构,它可以在线段上高效地 执行查询、更新和删除操作。
结构
线段树通常由一个根节点和若干个子 节点组成,每个节点包含一个区间的 信息,并且每个节点与其子节点之间 存在一一对应关系。
总结词
数组在随机访问和存储空间方面更具优势
详细描述
数组能够提供快速的随机访问,并且在相 同的数据量下,数组所需的存储空间可能 比线段树更少。
05 线段树的优缺点分析
线段树的优点
高效区间查询
线段树及其应用
为什么要用线段树?
if t=3 //询问一个区间的最小值、最大值、和 then begin readln(left,right); min:=a[left]; max:=a[left]; sum:=a[left]; for j:=left+1 to right do begin if a[j]<min then min:=a[j]; if a[j]>max then max:=a[j]; sum:=sum+a[j]; end; writeln(min,' ',max,' ',sum); end;
为什么要用线段树?
机器配置:Pentium 1.3G 512M
M,N的规模 M=100000,N=5000 M=100000,N=10000 M=100000,N=50000 M=100000,N=100000
一般的模拟 2.06秒 4.14秒 21.32秒 43.36秒
时间复杂度是线性的!
为什么要用线段树?
(1)对元素进行修改
procedure insert(cur:Node;x,num: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(LC,x,num); if x>(cur^.Left+cur^.Right) div 2 then insert(RC,x,num); cur^.Sum:=LC^.Sum+RC^.Sum; //上推 if (LC^.Max>RC^.Max) then cur^.Max:=LC^.Max else cur^.Max:=RC^.Max; if (LC^.Min<RC^.Min) then cur^.Min:=LC^.Min else cur^.Min:=RC^.Min; end; end;
线段树讲稿-BYVoid
《线段树》讲稿安徽师范大学附属中学杨弋前言在谈论到种种算法知识与数据结构的时候,线段树无疑总是与“简单”和“平常”联系起来的。
而这些特征意味着,线段树作为一种常用的数据结构,有常用性,基础性和易用性等诸多特点。
因此,今天我来讲一讲关于线段树的话题。
定义首先,线段树是一棵“树”,而且是一棵完全二叉树。
同时,“线段”两字反映出线段树的另一个特点:每个节点表示的是一个“线段”,或者说是一个区间。
事实上,一棵线段树的根节点表示的是“整体”的区间,而它的左右子树也是一棵线段树,分别表示的是这个区间的左半边和右半边。
在此我们可以举一个例子来说明线段树通常的构造方法,以RMQ问题为例:有N个数排成一排,每次询问某一段中的最小数。
构造的时候,让根节点表示区间[0,N-1],即所有N个数所组成的一个区间,然后,把区间分成两半,分别由左右子树表示。
不难证明,这样的线段树的节点数只有2N-1个,是O(N)级别的,如图:对于每个节点,不但要知道它所表示的区间,以及它的儿子节点的情况,也记录一些别的值,不然,一棵孤零零的树能有什么用?在这个例子里,由于要查询的东西是最小值,不妨在每个节点内记录下它所表示区间中的最小值。
这样,根据一个线性表构造出线段树的方法也就简单明白了:function 构造以v为根的子树if v所表示的区间内只有一个元素v区间的最小值就是这个元素, 构造过程结束end if把v所属的区间一分为二,用w和x两个节点表示。
标记v的左儿子是w,右儿子是x分别构造以w和以x为根的子树(递归)v区间的最小值<- min(w区间的最小值,x区间的最小值)end function这样,一棵线段树就建立好了。
不难证明构造过程是O(n)的,而线段树的高度是O(log n)的,准确地说,就是|log2 (n - 1)| + 1。
由构造过程可以发现,修改单个元素的操作异常简单:function modify(v, i, newvalue) // 把i的值修改为newvalue,当前处理的子树根节点是v if v所表示的区间内只有一个元素// 这个元素必定表示的就是[i, i]v区间的最小值<- newvalue退出函数end ifif (i属于v的左儿子的区间)modify(v的左儿子,i,newvalue)elsemodify(v的右儿子,i,newvalue)end ifv区间的最小值<- min(w区间的最小值,x区间的最小值) //更新数据end function由于每个节点都至多递归一次,它的时间复杂度= O(树深度) = O(log n)。
最新二分法与统计问题(线段树)
二分法与统计问题(线段树)二分法与统计问题 (线段树)OICF-信息学奥林匹克综合论坛[关键字]线段树二叉树二分法[摘要]我们经常遇到统计的问题。
这些问题的特点是,问题表现得比较简单,一般是对一定范围内的数据进行处理,用基本的方法就可以实现,但是实际处理的规模却比较大,粗劣的算法只能导致低效。
为了解决这种困难,在统计中需要借助一些特殊的工具,如比较有效的数据结构来帮助解决。
本文主要介绍的是分治的思想结合一定的数据结构,使得统计的过程存在一定的模式,以到达提高效率的目的。
首先简要介绍线段树的基础,它是一种很适合计算几何的数据结构,同时也可以扩充到其他方面。
然后将介绍 IOI2001 中涉及的一种特殊的统计方法。
接着将会介绍一种与线段树有所不同的构造模式,它的形式是二叉排序树,将会发现这种方法是十分灵活的,进一步,我们将略去对它的构造,在有序表中进行虚实现。
目录一线段树1.1 线段树的构造思想1.2 线段树处理数据的基本方法1.3 应用的优势1.4 转化为对点的操作二一种解决动态统计的静态方法2.1 问题的提出2.2 数据结构的构造和设想2.3 此种数据结构的维护2.4 应用的分析三在二叉排序树上实现统计3.1 构造可用于统计的静态二叉排序树3.2 进行统计的方法分析3.3 一个较复杂的例子四虚二叉树4.1 虚二叉树实现的形态4.2 一个具体的例子4.3 最长单调序列的动态规划优化问题[正文]一线段树在一类问题中,我们需要经常处理可以映射在一个坐标轴上的一些固定线段,例如说映射在 OX 轴上的线段。
由于线段是可以互相覆盖的,有时需要动态地取线段的并,例如取得并区间的总长度,或者并区间的个数等等。
一个线段是对应于一个区间的,因此线段树也可以叫做区间树。
1.1线段树的构造思想线段树处理的是一定的固定线段,或者说这些线段是可以对应于有限个固定端点的。
处理问题的时候,首先抽象出区间的端点,例如说 N 个端点 ti (1 ≤ i ≤ N) 。
【zkw线段树讲稿】统计的力量-线段树
*
清华大学 张昆玮
49
2013年1月8日
*
庄周梦蝶而已
清华大学 张昆玮
50
2013年1月8日
* 一根线段,支持区间染色。
询问区间是否同色?
* 区间染色需要使用染色标记 * 询问的时候就直接看标记嘛
1表示红色,2表示蓝色,3绿色,0杂色
*
清华大学 张昆玮
51
2013年1月8日
* 区间查询,穿刺查询都是计算几何解决的问题 * 作为特例中的特例,线段树解决的问题是:
* 一维空间上的几何统计
* 高维推广(kd-tree
& …)可以进行正交查询
* 由于竞赛中涉及计算几何的内容有限,不展开
*
清华大学 张昆玮
7
2013年1月8日
* 线段树把数轴分成区间来处理 * 如[8,10), [10,11), … * 实际上我们面对的往往是离散量 * 竞赛中出现的线段树往往因此退化为“点树” * 即,最底层的线段只包含一个点: * 如:[8,9)中只有整点8而已 * 在之后的讨论中,我们不再区别“点树”与线段
* Get 1
* Get [2,4) in [2,4)
* 虽然每次都有可能同时递归进入两棵子树,
但每层实际上只访问了两个节点。为什么?
* 因为查询是连续的啊……
*
清华大学 张昆玮
11
2013年1月8日
如果同一层有三个被访问,依次为A,B,C 查询是连续的,有了A和C,就一定包括B在树中的兄弟 那我直接用B的父亲来计算好了,为什么要用B?
*
清华大学 张昆玮
38
2013年1月8日
(…,5)?
线段树_刘汝佳(有版权)
SUM的计算
• 右图表示影响 SUM(7, 9)的所 有区间
– 影响全部: [1,9], [5,9], [7,9] – 影响部分: 7, [8,9], 8, 9
[1,2] 1 2 [1,9] [1,4] [3,4] 3 4 [5,9] [5,6] 5 6 [7,9] 7 [8,9] 8 9
完整的算法
– 得到讨论区间(可能要先离散化) – 设计区间附加信息和维护/统计算法
• 线段树自身没有任何数据, 不像BST一样有 一个序关系 • 警告 想清楚 警告: 想清楚附加信息的准确含义 不能有 准确含义, 准确含义 半点含糊! • 建议 先设计便于解题 建议: 便于解题的附加信息,如果难 便于解题 以维护就加以修改
[3,4]
5 3 3 5 5 1 1
[4,5]
5 3 3 5
1 2 2 3 3 4 4 5
1 2 2 3 3 4 4 5
1 2 2 3 3 4 4
1 2 2 3 3 4 4 5
矩形树
• 每个矩形分成四份
– 空间复杂度:XY – 时间复杂度:X+Y
(x2,y2) (1,1)
(4,3)
Son1
Son2
– ADD: 给i对应结点的所有直系祖先s值增加k – SUM: 做区间分解, 把对应结点的s值相加
动态统计问题II
• 包含n个元素的数组A
– ADD(i, j, k): 给A[i], A[i+1], … A[j]均增加k – QUERY(i): 求A[i]
• 先看看是否可以沿用刚才的附加信息
– QUERY(i)就是读取i对应的结点上的s值 – ADD呢? 极端情况下, 如果是修改整个区间, 则 所有结点都需要修改!
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
清华大学 张昆玮
3
*
• POJ上的某题,时限很紧…… • 大家都用树状数组,但是有人只会用线段树呢? • 而且我可以轻易改出一道不能用树状数组的题 • 在线段树一次次TLE后,有一个ID发帖抱怨 • “下次写一个汇编版非递归线段树,再超时?” • 可是大家都知道,超时的代码已经2k了。
• 其实我写的就是线段树。很快,而且不到1k。
• 虽然每次都有可能同时递归进入两棵子树, 但每层实际上只访问了两个节点。为什么?
• 因为查询是连续的啊……
清华大学 张昆玮
11
*
如果同一层有三个被访问,依次为A,B,C 查询是连续的,有了A和C,就一定包括B在树中的兄弟 那我直接用B的父亲来计算好了,为什么要用B?
清华大学 张昆玮
12
*
清华大学 张昆玮
• 遗憾的是,这种朴素的方法并不是那么容易实现
• 而且存在严重的效率问题(常数太大)
清华大学 张昆玮
18
*
清华大学 张昆玮
19
*
清华大学 张昆玮
工欲善其事,必先利其器。
20
*
清华大学 张昆玮
21
*
清华大学 张昆玮
22
*
• N 的左儿子是 2N • N 的右儿子是 2N + 1 • N 的父亲是 N >> 1 • …… • 不就是个堆存储么?不用讲了吧?
清华大学 张昆玮
4
*
• 运行速度快 • 适应能力强 • 编写方便 • 结构简单 • 容易调试 • 关键在于灵活实现
清华大学 张昆玮
5
*
为什么在《算法导论》和黑书中都难见到其踪迹?
清华大学 张昆玮
6
*
• 计算几何在长期的发展中, 诞生了许多实用的数据结构。
• 区间查询,穿刺查询都是计算几何解决的问题 • 作为特例中的特例,线段树解决的问题是:
• 在之后的讨论中,我们不再区别“点树”与线段树
清华大学 张昆玮
8
*
清华大学 张昆玮
如果我给MM的第一印象不到80分的话…… 是不是老老实实地早点罢手比较好?
9
*
清华大学 张昆玮
10
*
• [1,4) in [0,4)
• 左边,[1,2) in [0,2)
• Get 1
• Get [2,4) in [2,4)
清华大学 张昆玮
32
*
• 如果需要查询 0 就整个向后平移一下 • 所有下标加一!
• 如果需要在[0,1024)中查询1023结尾的区间? • 慢!你的数据规模不是 1000 么? • …… • 如果真的要到1023,直接把总区间变成[0,2048) • 就是这么狠!
清华大学 张昆玮
33
*
• Func Change(n,NewValue)
清华大学 张昆玮
23
*
清华大学 张昆玮
24
*
• 字母树! • 存放的是100,101,110,111四个串! • 每个节点存的是以这个节点为前缀的所有节点和 • 例:1中存的是所有四个以1开头的和。
• 似乎从 100 到 111 就正好是原数组 • 貌似……下标减 4 就行了?
清华大学 张昆玮
25
清华大学 张昆玮
30
*
• for (s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1) {
• if (~s&1) Ans+=T[s^1]; • if ( t&1) Ans+=T[t^1];
•}
清华大学 张昆玮
31
*
• 在将闭区间转化成开区间的时候可能越界1 • 理论上能放 [0,2^N) 的树 • 其实只能查询 [1,2^N - 2] 的范围 • 切记切记
*
• 我们可以直接找到一个数对应的叶子 • 不用自顶向下慢慢地找啊找 • “直接加 4 ”多简单!
• …… • 直接找到叶子? • 无限遐想中……
清华大学 张昆玮
26
*
清华大学 张昆玮
可以直接找到叶子?
27
*
清华大学 张昆玮
28
*
清华大学 张昆玮
29
*
• Func Query(s,t) // 询问从s到t闭区间
zkw线段树讲稿统计的 力量线段树
2020年4月22日星期三
• 根据 D. E. Knuth 的分类方法 计算机算法可以分为两类:
• 数值算法与非数值算法
• 其中的非数值算法包括:
• 索引 • 分类 • 统计 • ……
清华大学 张昆玮
2
*
• 大家都说: • …… • 常数很大? • 不好写? • 难调试? • 想不到? • ……
清华大学 张昆玮
15
*
数据结构 直接存储原数组 直接存储前缀和
线段树
修改元素 O(1) O(n)
O(logn)
取前缀和 O(n) O(1)
O(logn)
清华大学 张昆玮
16
*
清华大学 张昆玮
这个问题,本来是仁者见仁,智者见智的啊 但是我要讲一点不那么“本来”的东西
17
*
• 访问线段
• 如果要的是整条线段就直接返回 • 如果与左子线段相交就递归处理 • 如果与右子线段相交就递归处理 • 合并所得到的解
功利点说,没啥用的东西咱不学……
13
*
区区区间和,用的着线段树?
*直接把原数组处理成前缀和 *For i=2 to n do
*A[i]A[a] - A[b-1]
清华大学 张昆玮
14
*
• 原因是区间和的性质非常好 • 满足区间减法 • 区间减法什么的最讨厌了!后面再说! • 不过直接前缀和不是万能的! • 如果修改元素的话……
• s = s – 1, t = t + 1; // 变为开区间 • s += M, t += M; // 找到叶子位置 • While not ((s xor t) == 1) do
• If ((s and 1) == 0) Answer += Tree[s + 1]; • If ((t and 1) == 1) Answer += Tree[t – 1]; • s = s >> 1, t = t >> 1;
• n += M; • Tree[n] = NewValue; • While n > 1 do
• 一维空间上的几何统计
• 高维推广(kd-tree & …)可以进行正交查询
• 由于竞赛中涉及计算几何的内容有限,不展开
清华大学 张昆玮
7
*
• 线段树把数轴分成区间来处理 • 如[8,10), [10,11), … • 实际上我们面对的往往是离散量 • 竞赛中出现的线段树往往因此退化为“点树” • 即,最底层的线段只包含一个点: • 如:[8,9)中只有整点8而已