线段树的一些操作

const int maxn=2e5+5;
long long a[maxn];// 输入的数据数组
long long tree[maxn<<2]; //储存数组
long long add[4*maxn<<2];// 懒惰标记数组
void sum(int x) // 求和 //这个操作不太好说
{
    tree[x]=tree[x<<1]+tree[x<<1|1];  //存放的数据是左右子节点tree的和
}
void build (int l,int r,int x) //建立二叉树
{
    if(l==r)
    {
          tree[x]=a[l]; // 当l=r时,已经走到了叶子节点,把输入的数据放到叶子节点中
          return ;
    }
    build(l,(l+r)/2,x<<1);
    build((l+r)/2+1,r,x<<1|1);
    sum(x);  //求出该节点存放孩子节点之和
}
void pushdown(int l,int r,int x) //相当于标记吧
{
       add[x<<1]+=add[x];//下推 懒惰标记,标记的是叶子结点应该加上的数值
       add[x<<1|1]+=add[x];//下推 同上
       tree[x<<1]+=tree[x]*l; //这个改变得是该节点的叶子 子结点有多少个,就应该改变多少
       tree[x<<1|1]+=tree[x]*r;//同上
       add[x]=0;//当前节点信息已更新 因此懒惰标记应该清除
}
long long query(int L,int R,int l,int r,int x)// 查询L到R的区间和
{
       if(l>=L&&r<=R) return tree[x]; //意思是当满足条件有tree[x]存的是从l到r的区间和,因此可直接返回,不用再继续递归
       long long ans=0;
       int m=(l+r)/2;
       pushdown(m-l+1,r-m,x);// 下推 保证数据的正确性
       if(L<=m) ans+=query(L,R,l,m,x<<1);  //继续划分,区间求和,一直到L==l
       if(R>m) ans+=query(L,R,m,r,x<<1|1);// R==r
       return ans;
}
void update(int id,long long  ans,int l,int r,int x)// 对于点的更新
{
      if(l==r) {tree[x]+=ans;return ;} //表示已找到该节点
      int m=(l+r)/2;
      if(id<=m) update(id,ans,l,m,x<<1);  // id 在左子树上
      else update(id,ans,m+1,r,x<<1|1); // 如果id在you子树
      sum(x); //求和
}
void Update(int L,int R,long long ans,int l,int r,int x)//区间更新
{
       if(L<=l&&r<=R)
       {
            tree[x]+=ans*(r-l+1);//意思是当满足条件有tree[x]存的是从l到r的区间和,因此可直接更新,不用再继续递归
            add[x]+=ans;//在该节点标记一下
            return ;
        }
       int m=(l+r)/2;
       pushdown(m-l+1,r-m,x); //下推 保证数据的正确性
       if(L<=m) Update(L,R,ans,l,m,x<<1);
       if(R>m) Update(L,R,ans,m+1,r,x<<1|1);
       sum(x);// 求和
}

个人见解:对于点的更新(update)可以省略,可以看做是区间大小为1的更新(Update)

函数引用:

build(l,r,1); //建树
query(L,R,1,n,x); //查询
update(id,ans,1,n,x); //点修改
Update(L,R,ans,l,n,x);//区间修改


数组开maxn<<2? 点击这里

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值