动态开点线段树
#include<iostream> #include<cstdio> #define ri register int #define u long long namespace opt { inline u in() { u x(0),f(1); char s(getchar()); while(s<'0'||s>'9') { if(s=='-') f=-1; s=getchar(); } while(s>='0'&&s<='9') { x=(x<<1)+(x<<3)+s-'0'; s=getchar(); } return x*f; } } using opt::in; #define NN 100005 namespace xds { struct node{ u l,r,sum,add; }a[NN<<1]; u num,root; void pushdown(const u &rt,const u &l,const u &r){ if(a[rt].add){ if(!a[rt].l) a[rt].l=++num; if(!a[rt].r) a[rt].r=++num; u mid((l+r)>>1); a[a[rt].l].add+=a[rt].add; a[a[rt].r].add+=a[rt].add; a[a[rt].l].sum+=a[rt].add*(mid-l+1); a[a[rt].r].sum+=a[rt].add*(r-mid); a[rt].add=0; } } void update(u &rt,const u &l,const u &r,const u &x,const u &y,const u &k){ if(!rt) rt=++num; if(l>=x&&r<=y){ a[rt].sum+=k*(r-l+1),a[rt].add+=k; return; } pushdown(rt,l,r); u mid((l+r)>>1); if(x<=mid) update(a[rt].l,l,mid,x,y,k); if(y>=mid+1) update(a[rt].r,mid+1,r,x,y,k); a[rt].sum=a[a[rt].l].sum+a[a[rt].r].sum; } u query(const u &rt,const u &l,const u &r,const u &x,const u &y){ if(!rt) return 0; if(l>=x&&r<=y) return a[rt].sum; pushdown(rt,l,r); u mid((l+r)>>1),_re(0); if(x<=mid) _re+=query(a[rt].l,l,mid,x,y); if(y>=mid+1) _re+=query(a[rt].r,mid+1,r,x,y); return _re; } } namespace mainstay { inline void solve(){ u N(in()),M(in()),_a; for(ri i(1);i<=N;++i) _a=in(),xds::update(xds::root,1,N,i,i,_a); for(ri i(1);i<=M;++i){ u k(in()); if(k==1){ u l(in()),r(in()),_x(in()); xds::update(xds::root,1,N,l,r,_x); } else{ u l(in()),r(in()); printf("%lld ",xds::query(xds::root,1,N,l,r)); } } } } int main() { //freopen("x.txt","r",stdin); std::ios::sync_with_stdio(false); mainstay::solve(); }