UKE_Piu @ 2023-11-19 23:12:06
#include<iostream>
#define ll long long
using namespace std;
int n,m;
const int N=1e5+5;
ll a[N];
struct SegTree{
struct node {
ll w;
ll lzy;
};
node tr[N<<2];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
void pushup(int u){
tr[u].w=tr[ls(u)].w+tr[rs(u)].w;
}
void build(int u,int L,int R){
if(L==R){
tr[u].w=a[L];
return ;
}
int M=L+(R-L)/2;
build(ls(u),L,M);
build(rs(u),M+1,R);
pushup(u);
return ;
}
bool In_Range(int x,int y,int L,int R){
return (L>=x)&&(R<=y);
}
bool Outof_Range(int x,int y,int L,int R){
return (L>y)||(R<x);
}
void maketag(int u,ll len,ll tag){
tr[u].w+=len*tag;
tr[u].lzy+=tag;
}
void pushdown(int u,int L,int R){
int M=L+(R-L)/2;
maketag(ls(u),1ll*(M-L+1),tr[u].lzy);
maketag(rs(u),1ll*(R-M),tr[u].lzy);
}
ll query(int u,int x,int y,int L,int R){
if(In_Range(x,y,L,R)) return tr[u].w;
else if(Outof_Range(x,y,L,R)) return 0;
else {
pushdown(u,L,R);
int M=L+(R-L)/2;
return query(ls(u),x,y,L,M)+query(rs(u),x,y,M+1,R);
}
}
void update(int u,int x,int y,int L,int R,ll k){
if(In_Range(x,y,L,R)) maketag(u,R-L+1,k);
else if(Outof_Range(x,y,L,R)) return ;
else {
int M=L+(R-L)/2;
pushdown(u,L,R);
update(ls(u),x,y,L,M,k);
update(rs(u),x,y,M+1,R,k);
pushup(u);
}
}
};
SegTree T;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
T.build(1,1,n);
while(m--){
int op;
int x,y;
ll k;
cin>>op;
if(op==1){
cin>>x>>y>>k;
T.update(1,x,y,1,n,k);
}
else {
cin>>x>>y;
cout<<T.query(1,x,y,1,n)<<endl;
}
}
return 0;
}
by Xlw6friend @ 2023-11-19 23:30:49
头一次见线段树用struct,我建议你先把书上的抄一遍在慢慢理解
by wosile @ 2023-11-20 08:00:35
@Xlw6friend 线段树用 struct 是很正常的写法。
by wosile @ 2023-11-20 08:03:14
@jscbhbc1 pushdown 最后应有 tr[u].lzy=0;
来清空已经下传的 tag。改完就过了。
by UKE_Piu @ 2023-11-23 13:31:08
@wosile 拜谢大佬,过了