大家好~ o( ̄▽ ̄)ブ
经过1.919810天的奋斗(误)
一份带懒标记的线段树模板新鲜出炉!!!
#include<iostream>
using namespace std;
struct tree{
/*左边界,右边界,区间和,懒标记*/
long long l,r,v,lazy;
}tre[1919810];/*(首)*/
/*递归式建树*/
inline void b_t(long long id,long long left,long long right){
/*初始化区间*/
tre[id].l=left;tre[id].r=right;
/*特判叶子节点*/
if(left==right){scanf("%lld",&tre[id].v);return ;}
/*求左右子树分界*/
long long mid=(left+right)>>1;
/*递归 左 子树*/
b_t(id<<1,left,mid);
/*递归 右 子树*/
b_t((id<<1)+1,mid+1,right);
/*区间和*/
tre[id].v=tre[id<<1].v+tre[(id<<1)+1].v;
/*
if(tre[id*2].v>tre[id*2+1].v) {
tre[id].v=tre[id*2].v;
}else{
tre[id].v=tre[id*2+1].v
}//区间最值
*/
return ;
}
inline void d_n(long long id){
/*lazy tag下传*/
tre[id<<1].lazy+=tre[id].lazy;
tre[(id<<1)+1].lazy+=tre[id].lazy;
/*子节点lazy sum计算*/
tre[id<<1].v+=tre[id].lazy*(tre[id<<1].r-tre[id<<1].l+1);
tre[(id<<1)+1].v+=tre[id].lazy*(tre[(id<<1)+1].r-tre[(id<<1)+1].l+1);
/*父节点lazy tag清零*/
tre[id].lazy=0;
return ;
}
inline long long ask_p(long long id){/*单点查询*/
long long i=1;/*初始化节点编号*/
for(int mid;tre[i].l!=tre[i].r;){
/*lazy tag下传 (line 30)*/
if(tre[i].lazy){d_n(i);}
/*求左右子树分界*/
mid=(tre[i].l+tre[i].r)>>1;
if(id<=mid){
i<<=1;/*向 左 子树查找*/
}else{
i<<=1;i++;/*向 右 子树查找*/
}
}
return tre[i].v;
}
inline void ad_p(long long id,long long num){/*单点增加*/
long long i=1;/*初始化节点编号*/
for(int mid;tre[i].l!=tre[i].r;){
tre[i].v+=num;
/*求左右子树分界*/
mid=(tre[i].l+tre[i].r)>>1;
if(id<=mid){
i<<=1;/*向 左 子树查找*/
}else{
i<<=1;i++;/*向 右 子树查找*/
}
}
tre[i].v+=num;
return ;
}
inline long long ask_s(long long left,long long right,long long id){
/*lazy tag下传 (line 30)*/
if(tre[id].lazy){d_n(id);}
/*判断该节点是否在区间内*/
if(tre[id].l>=left && tre[id].r<=right){
return tre[id].v;
}/*若是,则加和并返回*/
long long mid=(tre[id].l+tre[id].r)>>1,res=0;
/*若包含 左 子树*/
if(tre[id].l<=left && left<=mid){
if(mid<right){
res+=ask_s(left,mid,id<<1);
}else{
res+=ask_s(left,right,id<<1);
}/*递归 左 子树*/
}
/*若包含 右 子树*/
if(mid<right && right<=tre[id].r){
if(left<=mid){
res+=ask_s(mid+1,right,(id<<1)+1);
}else{
res+=ask_s(left,right,(id<<1)+1);
}/*递归 右 子树*/
}
return res;
}
inline void ad_s(long long left,long long right,long long num,long long id){
/*判断该节点是否在区间内*/
if(tre[id].l>=left && tre[id].r<=right){
tre[id].v+=(tre[id].r-tre[id].l+1)*num;
tre[id].lazy+=num;return ;
}/*若是,则更新lazy tag并返回*/
long long mid=(tre[id].l+tre[id].r)>>1;
/*若包含 左 子树*/
if(tre[id].l<=left && left<=mid){
if(mid<right){
ad_s(left,mid,num,id<<1);
}else{
ad_s(left,right,num,id<<1);
}/*递归 左 子树*/
}
/*若包含 右 子树*/
if(mid<right && right<=tre[id].r){
if(left<=mid){
ad_s(mid+1,right,num,(id<<1)+1);
}else{
ad_s(left,right,num,(id<<1)+1);
}/*递归 右 子树*/
}
if(left<tre[id].l){left=tre[id].l;}
if(tre[id].r<right){right=tre[id].r;}
tre[id].v+=(right-left+1)*num;
/*更新自身*/
return ;
}
long long n,m,mod,a,b,c;
int main(){
scanf("%lld %lld",&n,&m);
b_t(1,1,n);/*递归式建树 (line 8)*/
while(m--){
scanf("%lld %lld",&mod,&a);
if(mod==0){
printf("%lld\n",ask_p(a));
}else if(mod==1){
scanf("%lld",&b);
ad_p(a,b);
}else if(mod==2){
scanf("%lld",&b);
printf("%lld\n",ask_s(a,b,1));
}else if(mod==3){
scanf("%lld %lld",&b,&c);
ad_s(a,b,c,1);
}
}
return/*结束*/0;
}/*
0 a:查询数组中下标为a的数;
1 a b:将数组中第a个数增加b;
2 a b:查询数组中从a到b的若干个数之和;
3 a b c:将数组中从a到b的若干个数分别增加c;
<z
^z
*/
码字不易,给本蒟蒻猫猫点个赞吧QwQ