線段樹_[模板]
阿新 • • 發佈:2020-08-20
#include<iostream> #include<cmath> #include<algorithm> #include<cstdio> using namespace std; int n,m; long long a[100005]; long long tree[10000005]; int d[10000005][3]; long long lazy[10000005]; void buildtree(int root,int s,int t) { if (s==t) { tree[root]=a[s]; d[root][1]=s; d[root][2]=t; return; } buildtree(root*2,s,(s+t)/2); buildtree(root*2+1,(s+t)/2+1,t); tree[root]=tree[root*2]+tree[root*2+1]; d[root][1]=s; d[root][2]=t; } void down(int root) { if(lazy[root]!=0) { tree[root*2]+=(d[root*2][2]-d[root*2][1]+1)*lazy[root]; tree[root*2+1]+=(d[root*2+1][2]-d[root*2+1][1]+1)*lazy[root]; lazy[root*2]+=lazy[root]; lazy[root*2+1]+=lazy[root]; lazy[root]=0; } } void change(int root,int s,int t,int l,int r,int add) { if (t<l || s>r) return; if (l<=s && r>=t) { tree[root]+=(d[root][2]-d[root][1]+1)*add; lazy[root]+=add; return; } down(root); int mid=(s+t)/2; change(root*2,s,mid,l,r,add); change(root*2+1,mid+1,t,l,r,add); tree[root]=tree[root*2]+tree[root*2+1]; } long long find(int root,int s,int t,int l,int r) { if (t<l || s>r) return 0; if (l<=s && r>=t) { return (tree[root]); } down(root); return (find(root*2,s,(s+t)/2,l,min(r,(s+t)/2))+find(root*2+1,(s+t)/2+1,t,max(l,(s+t)/2+1),r)); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); buildtree(1,1,n); for(int i=1;i<=m;i++) { long long k,a,b,c; scanf("%lld",&k); if (k==1) { scanf("%lld%lld%lld",&a,&b,&c); change(1,1,n,a,b,c); } if (k==2) { scanf("%lld%lld",&a,&b); printf("%lld\n",find(1,1,n,a,b)); } } }