#树# #线段树#

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#树# #线段树#相关的知识,希望对你有一定的参考价值。

线段树

                      技术分享

线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
 
模板:
建树
 1 void Pushup(int rt){//根节点求和 
 2     segtree[rt]=segtree[rt<<1]+segtree[rt<<1|1];
 3 }
 4 
 5 void build(int l,int r,int rt){//建树
 6     if(l==r){
 7         scanf("%d",&segtree[rt]);
 8         return;
 9     }
10     int mid=l+r>>1;
11     build(l,mid,rt<<1);
12     build(mid+1,r,rt<<1|1);
13     Pushup(rt);
14 }

 

单点修改

 1 void Pushup(int rt){//根节点求和 
 2     segtree[rt]=segtree[rt<<1]+segtree[rt<<1|1];
 3 }
 4 
 5 void update(int p,int x,int l,int r,int rt){//单点修改 
 6     if(l==r){
 7         segtree[rt]+=x;//segtree[rt]=x;
 8         return;
 9     }
10     int mid=l+r>>1;
11     if(p<=mid)update(p,x,l,mid,rt<<1);
12     else update(p,x,mid+1,r,rt<<1|1);
13     Pushup(rt);
14 }

 

区间求和

int query(int L,int R,int l,int r,int rt){//区间求和 
    if(l>=L&&r<=R)return segtree[rt];
    int mid=l+r>>1;
    int ans=0;
    if(L<=mid)ans+=query(L,R,mid,l,rt<<1);
    if(R>mid)ans+=query(L,R,mid+1,r,rt<<1|1);
    return ans;
}

 

区间最小值
 1 void Pushup(int rt){//
 2     segtree[rt]=min(segtree[rt<<1],segtree[rt<<1|1]);
 3 }
 4 
 5 void build(int l,int r,int rt){//建树
 6     if(l==r){
 7         scanf("%d",&segtree[rt]);
 8         return;
 9     }
10     int mid=l+r>>1;
11     build(l,mid,rt<<1);
12     build(mid+1,r,rt<<1|1);
13     Pushup(rt);
14 }
15 
16 int query(int L,int R,int l,int r,int rt){//区间求最小值 
17     if(l>=L&&r<=R)return segtree[rt];
18     int mid=l+r>>1;
19     int ans=6452389;
20     if(L<=mid)ans=min(ans,query(L,R,l,mid,rt<<1));
21     if(R>mid) ans=min(ans,query(L,R,mid+1,r,rt<<1|1));
22 }

 

区间最大值

 1 void Pushup(int rt){
 2     segtree[rt]=max(segtree[rt<<1],segtree[rt<<1|1]);
 3 }
 4 
 5 void build(int l,int r,int rt){//建树
 6     if(l==r){
 7         scanf("%d",&segtree[rt]);
 8         return;
 9     }
10     int mid=l+r>>1;
11     build(l,mid,rt<<1);
12     build(mid+1,r,rt<<1|1);
13     Pushup(rt);
14 }
15 
16 int query(int L,int R,int l,int r,int rt){//区间求最大值 
17     if(l>=L&&r<=R)return segtree[rt];
18     int mid=l+r>>1;
19     int ans=6452389;
20     if(L<=mid)ans=max(ans,query(L,R,l,mid,rt<<1));
21     if(R>mid) ans=max(ans,query(L,R,mid+1,r,rt<<1|1));
22 }

 

区间修改

 1 void Pushup(int rt){//根节点求和 
 2     segtree[rt]=segtree[rt<<1]+segtree[rt<<1|1];
 3 }
 4 
 5 void Pushdown(int rt,int len){//向下更新
 6     if(add[rt]){
 7         add[rt<<1]+=add[rt];
 8         add[rt<<1|1]+=add[rt];
 9         segtree[rt<<1]+=add[rt]*(len-(len>>1));
10         segtree[rt<<1|1]+=add[rt]*(len>>1);
11         add[rt]=0;
12     }
13 }
14 
15 void update(int L,int R,int x,int l,int r,int rt){//区间修改 
16     if(l>=L&&r<=R){
17         add[rt]+=x;
18         segtree[rt]+=x*(r-l+1);
19         return;
20     }
21     Pushdown(rt,r-l+1);
22     int mid=l+r>>1;
23     if(L<=mid)update(L,R,x,l,mid,rt<<1);
24     if(R>mid)update(L,R,x,mid+1,r,rt<<1|1);
25     Pushup(rt);
26 }

 

以上是关于#树# #线段树#的主要内容,如果未能解决你的问题,请参考以下文章

线段树

线段树合并

论线段树:二

高级数据结构线段树

线段树-代码实现细节与技巧

BZOJ 4756 线段树合并(线段树)