直接复制过来的效果太差了
还是移步去https://www.cnblogs.com/TenosDoIt/p/3453089.html吧
还有这个 https://www.cnblogs.com/ACworker/p/7703537.html
线段树从零开始,
https://blog.youkuaiyun.com/zearot/article/details/52280189
超详细的模板哦
#include <bits/stdc++.h>
using namespace std;
/*定义*/
#define maxn 100007 //元素总个数
int sum[maxn<<2];//sum求和 开四倍空间
int a[maxn],n;//存原数组下标[1,n]
int add[maxn<<2];//懒惰标记
/*建树*/
//pushup 函数更新节点信息,这里是求和。
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
//build 函数建树
void build(int l,int r,int rt)
{//[l,r] 表示当前节点区间, rt 是当前节点实际存储位置
if(l==r) {//若到达叶节点
sum[rt]=a[l];//存储a数组的值
return ;
}
int mid=(l+r)>>1;
//左右递归
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
//更新信息
pushup(rt);
}
//点修改
void update_dot(int L,int C,int l,int r,int rt)
{//[l,r]表示当前区间 rt是当前节点编号
if(l==r)
{
sum[rt]+=C;
return ;
}
int mid=(l+r)>>1;
//根据条件判断往左子树调用还是往右
if(L<=mid) update_dot(L,C,l,mid,rt<<1);
else update_dot(L,C,mid+1,r,rt<<1|1);
pushup(rt);//子节点的信息更新了,所以本节点也要更新
}
//区间修改
void update_qu(int L,int R,int C,int l,int r,int rt)
{//L,R表示操作区间 l,r 表示当前节点区间,rt表示当前节点编号
if(l>=L&&R>=r)//如果本区间完全在操作区间[L,R] 之内
{
sum[rt]+=C*(r-l+1);//更新数字和,向上保持正确
add[rt]+=C;//增加add标记 表示 本区间的sum正确,子区间的sum仍需要根据add的值来调整
return ;
}
int mid=(l+r)>>1;
pushdown(rt,mid-l+1,r-mid);//下推标记
//这里判断左右子树跟[L,R]有无交集,有交集才递归
if(L<=mid) update_qu(L,R,C,l,mid,rt<<1);
if(R>mid) update_qu(L,R,C,mid+1,r,rt<<1|1);
pushup(rt);//更新本节点信息
}
// 下推标记
void pushdown(int rt,int ln,int rn)
{//ln rn 为 左子树 右子树的数字数量
if(add(rt))
{
//下推标记
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
//修改子节点的sum使之与对应的add相对应
sum[rt<<1]+=add[rt]*ln;
sum[rt<<1|1]+=add[rt]*rn;
//清除本节点的标记
add[rt]=0;
}
}
//区间查询 (求[L,R]和)
int Query(int L,int R,int l,int r,int rt)
{//[L,R]表示操作区间 [l,r]表示当前区间 rt表示当前节点编号
if(l>=L&&R>=r)
{//在区间内直接返回
return sum[rt];
}
int mid=(l+r)>>1;
//左[l,mid] 右[mid+1,r] 求和区间[L,R];
//累加答案
int ans=0;
if(L<=mid) ans+=Query(L,R,l,mid,rt<<1);//左子区间与[L,R]有重叠,递归
if(R>mid) ans+=Query(L,R,mid+1,r,rt<<1|1);//右子区间与[L,R]有重叠,递归
return ans;
}
/*懒惰标记
含义:本节点的统计信息已经根据标记更新过了,但是本节点的节点仍需要
进行更新
*/
//建树
build(1,n,1);
//点修改
update_dot(L,C,1,n,1);
//区间修改
update_qu(L,R,C,1,n,1);
//区间查询
int ANS=Query(L,R,1,n,1);