线段树模板

总结了一下线段树的基本运用和操作,也方便日后知识的梳理和Ctrl C+V提高AC率

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define N 100//N是题目给的最大区间,而节点数要开4倍,确切的来说节点数要开大于maxn的最小2x的两倍
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;

int sum[N*2];
int n;
int col[N<<2]

inline void pushup(int rt)//从其子节点更新当前节点 
 {
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 }
inline void build(int l,int r,int rt)//建树 
 {
    if(l==r)
     {
        scanf("%d",&sum[rt]);
        return;
      }
    int m=(l+r)>>1;  
    build(lson);
    build(rson);
    pushup(rt); 
  } 

 inline int query(int L,int R,int l,int r,int rt)//求区间[L,R]的和 ,也可以查询区间最值 
  {
    if(L<=l&&R>=r)return sum[rt];//若要求的区间[L,R]包括递归到的区间[l,r]则加上该节点的值 
    int m=(l+r)>>1;
    int ret=0;
    if(L<=m)ret+=query(L,R,lson);//向右递归 ,查询区间最值就直接把+=改为max或者min就好 
    if(R>m)ret+=query(L,R,rson);//向左递归 
    return ret;
   } 

   inline void update(int p,int add,int l,int r,int rt)//单点增减或改变 
    {
        if(l==r)
         {
            sum[rt]+=add;//单点增减 
            //sum[rt]=add;单点更换 
            return; 
         }
        int m=(l+r)>>1;
        if(p<=m)update(p,add,lson);
         else update(p,add,rson);
        pushup(rt);//因为更新了子节点,自然要维护,所以父节点也要变  
    }
    inline void pushdown(int rt,int m)//延迟更新 ,其实本质上不过是只更新父节点,然后有需要才更新子节点 
     {                   //举个例子,有一家企业,政府要来检查某一个部门的总薪资,这个部门的领导为了增加腰包(贪腐),就多报了。 
        if(col[rt])                                   //至于下面一层层工人就打个标记,政府检查到哪个就给哪个把薪资加上,这样就可以最大限度增加腰包 
         {                                            //对于我们来说这么做线段树就可以只应付需要的部分,若是不用(政府不检查)就不用更新,就可以减小时间复杂度 
            col[rt<<1]=col[rt<<1|1]=col[rt];
            sum[rt<<1]+=(m-(m>>1))*col[rt];
            sum[rt<<1|1]+=(m>>1)*col[rt];
            col[rt]=0;
          }
     }
     void update(int L,int R,int c,int l,int r,int rt) //整个区间[l,r]增减c或者改变为c 
      {                                              //总体上和单点修改差不多,就多了要标记一下,和判断一下当前节点rt是否被标记 
        if (L<=l&&R>=r) 
        {
              col[rt]=c;
              sum[rt]=c*(r - l + 1);
              return;
        }
        pushdown(rt,r-l+1);

        int m=(l+r)>>1;
        if (L<=m) update(L,R,c,lson);
        if (R>m) update(L,R,c,rson);
        pushup(rt);
 }
 inline int query(int L,int R,int l,int r,int rt) //延迟标记时的区间求和,其实就是多了个处理标记的~~~ 
  {
        if (L<=l&&R>=r) return sum[rt];

        pushdown(rt,r-l+1);
        int m=(l+r)>>1;
        int ret=0;
        if(L<=m)ret+=query(L,R,lson);
        if(m<R)ret+=query(L,R,rson);
        return ret;
 }
int main()
 {

 }

延迟更新(或者说懒惰更新)是在要修改这个节点或查询这个节点时做的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值