ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

线段树入门

2021-08-04 11:34:47  阅读:144  来源: 互联网

标签:rt 入门 int 线段 SegTree void 区间 节点


 

线段树构造

//PushUp函数更新节点信息,这里以求和为例
​
void PushUp(int rt){ 
​
SegTree[rt].val = SegTree[rt<<1].val + SegTree[rt<<1|1].val;
​
 }
​
void build(int l, int r, int rt ){//构造根为rt,A区间为[l,r]线段树
if(1 == r){      //叶子节点
SegTree[rt].val = A[1];
return;
}
int m = (l +r) / 2;build(1,m,rt*2);    //递归构造左子树
build(m+1,r,i rt*2+1);    //递归构造右子树
PushUp(rt);     //回溯,向上更新

单点更新(假设A[L]+=C)

//1,r表示当前节点区间,rt表示当前线段树的根节点编号
void Update(int(L,intC int 1,int r, int rt){
if(1==r){       //叶节点,直接修改
SegTree[rt].val += C;
return;
}
int m=(1+r)>>1;
if(L<= m) Update(L,C,1,m, rt<<1)
 else      Update(L,C,m+1,r,rt<<1| 1);
PushUp(rt);      //回溯,向上更新
​
​

区间查询( 询问A[L..R]的和)

//[L,R]表示操作区间,[1,r]表示当前区间,rt表示当前节点编号
int Query(int L,int R, int l,int r,int rt) {
if(L<=l&&r<=R)
   return SegTree[rt].val; //在区间内 直接返回
if(L>r||R<l )
   return 0;
int m=(l+r)>> 1;
int ANS = 0;
if(L <= m) ANS+=Query(L,R,l,m,rt<<1);//左子区间与[L,R]有重叠,递归
if(R> m) ANS+=Query(L, R, m+1,r,rt<<1|1); //右子区间与[L,R]有重叠,递归
return ANS;
// return Query(L,R,l,m,rt<<1) + Query(L,R, m+1,r,rt<<1|1);

线段树的构造(有Iazy标记)

//构造根为rt,A区间为[l,r]线段树
void build(int l,int r,int rt ){
SegTree[rt]. lazy=0;// 初始化延时标记为0_
if(1=r){   //叶子节点
SegTree[rt]. val = A[1];
return;
}
intm=(1+r)/2;
build(1,m,rt*2) ;       //递归构造左子树
build (m+1, r,rt*2+1) ;   //递归构造右子树
PushUp(rt) ;   //回溯,向上更新
}

区间更新(以A[L,R]+=C为例)

void Update(int L,int R, int C,int l,int r, int rt) {
if(L<=l&&r<=R){
SegTree[rt]. val+=C*(r-1+1); //更新数字和,向上保持正确
SegTree[rt].lazy+=C;   //累加还是赋值,看需求
return ;
}
int m=(1+r)>>1;
 PushDown (rt, m-l+1,r-m) ;  //下推以后,才准确更新子节点
if(L <= m) Update(L,R,C,1,m,rt<<1);
if(R > m)  Update(L,R,C,m+1,r, rt<<1|1);
PushUp (rt);         //更新本节点信息
}

区间更新( 以A[L,R] +=C为例)

//ln, rn分别为左子树和右子树的区间大小
void PushDown(int rt,int ln,int rn) {
if (SegTree[rt]. lazy) {   //下推标记
SegTree[rt<<1]. lazy += SegTree[rt]. lazy;
SegTree[rt<<1|1]. lazy += SegTree[rt]. lazy;
SegTree[rt<<1]. val += SegTree[rt]. lazy * ln;
SegTree[rt<<1|1]. val += SegTree[rt]. lazy * rn;

SegTree[rt]. lazy = 0;//清除本节 点标记
}
}

区间更新的区间查询(询问A [L..R]的和)

//[L,R]表示操作区间,[1,r]表示当前区间,rt表示当前区间根节点编号|
int Query(intL,int R,int l,int r,int rt) {
if(L <=l && r <=R)
return SegTree[rt]. val; //在区间内直 接返回
if(L> r|| R<l )
return 0;
int m=(l+r)>> 1;
 PushDown(rt, m-l+1,r-m) ; //下推以后,才准确查询子节点
return Query(L,R,l,m,rt<<1) + Query(L, R, m+1,r,rt<<1|1);

 

标签:rt,入门,int,线段,SegTree,void,区间,节点
来源: https://www.cnblogs.com/yhj-coisini/p/15098060.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有