线段树学习笔记
来源:互联网 发布:华为机顶盒 mac地址 编辑:程序博客网 时间:2024/05/16 12:05
线段树,就是一棵由线段构成的二叉树,每个节点代表一条线段[a,b],非叶子的结点所对应的线段都有两个子结点,左儿子代表的线段为[a,a+b/2],右儿子代表的线段为[a+b/2+1,b]类似二分的思想;
线段树可以查找并修改连续区间内的信息,优化区间操作;
如:对序列A1,A2,A3……An,操作 1 x v表示给Ax+v
操作 2 x y查询,即询问[Ax,Ay]的区间和;
当x=5 n=8
根节点为[1,8]
sum[1,8]+=v
其两个子节点为[1,4] [5,8]
因为x∈[5,8] 我们选择右儿子
sum[5,8]+=v
以此类推,直到当前结点为[5,5]
中间选择的每个子节点的sum都要加上v
长度范围为[1,n]的一棵线段树的深度为log(n)+1.
单次修改区间数量是log级别,复杂度O(logn)
void change(int p,int left,int right,int x,int v){ sum[p]+=v; int t=(left + right)/2; if(left==right) return;//如果已经是叶子 if(x<=t)//如果左儿子 change(p*2,left,t,x,v); else change(p*2+1,t+1,right,x,v);}
注意,对于一个节点p,其左子节点、右子节点的编号分别为2*p,2*p+1;
而对于查询,当x=5,y=7,n=8;我们需要求出[A5,A7]的信息
[A5,A7]又等于[5,6],[7,7]的并,由于线段树每层的结点最多只会被选取两个,所以查询是O(logn)
int ask(int p,int left,int right, int x,int y){ if(x<=left&&right<=y)//在查询区间内 return sum[p]; int t=(left+right)/2,res=0; if(x<=t) res+=ask(p*2,left,t,x,y); if(y>t) res+=ask(p*2+1,t+1,right,x,y); return res;}
阅读全文
0 0
- 学习笔记 线段树
- 线段树学习笔记
- 线段树学习笔记
- 学习笔记 --- 线段树
- 线段树学习笔记
- 线段树学习笔记
- 线段树学习笔记
- 线段树学习笔记01
- Algorithm学习笔记 --- 线段树
- C#学习笔记:线段树
- 线段树学习笔记//日记
- Algorithm学习笔记 --- 线段树单点更新
- 学习笔记:可持久化线段树
- |算法讨论|线段树2 学习笔记
- 线段树学习笔记及模板
- 【线段树】Codevs线段树练习1.2.3及线段树学习笔记
- 学习笔记——线段树算法学习
- unity 渲染线段 学习笔记
- Shiro 自定义realm认证
- I/O流--File类
- Java线程池
- Ajax基础详解1
- 怎样辨别一个处理器的架构?
- 线段树学习笔记
- Http请求
- JVM内存管理
- [设计模式]策略模式
- zookeeper技术内幕一
- Spring Aop切面
- oracle插入返回主键&&根据时间获取最新的一条数据
- 个人赛 3 最后一题 联通图概率dp
- 注意事项