洛谷P3372 【模板】线段树 1
作者:互联网
两个操作,第一个打懒标记处理,第二个直接询问即可,线段树中每个节点存的是区间内所有元素之和。
1 //p3372 2 #include<bits/stdc++.h> 3 typedef long long ll; 4 using namespace std; 5 #define lson k<<1,l,mid 6 #define rson k<<1|1,mid+1,r 7 const int N=1e5+10; 8 int n,m; 9 struct node{ 10 int l,r; 11 ll sum,tag; 12 }t[N<<2]; 13 14 void rev(int k,ll x){ 15 t[k].sum+=x*(t[k].r-t[k].l+1); 16 t[k].tag+=x; 17 } 18 19 void pushdown(int k){ 20 rev(k<<1,t[k].tag); 21 rev(k<<1|1,t[k].tag); 22 t[k].tag=0; 23 } 24 25 void pushup(int k){ 26 t[k].sum=t[k<<1].sum+t[k<<1|1].sum; 27 } 28 29 void build(int k,int l,int r){ 30 t[k].l=l;t[k].r=r; 31 if(l==r){ 32 scanf("%d",&t[k].sum); 33 return ; 34 } 35 int mid=(l+r)>>1; 36 build(lson);build(rson); 37 pushup(k); 38 } 39 40 void change(int k,int l,int r,ll x){ 41 if(t[k].l>=l && t[k].r<=r){ 42 rev(k,x);return ; 43 } 44 pushdown(k); 45 int mid=(t[k].l+t[k].r)>>1; 46 if(l<=mid) change(k<<1,l,r,x); 47 if(r>mid) change(k<<1|1,l,r,x); 48 pushup(k); 49 } 50 51 ll query(int k,int l,int r){ 52 if(t[k].l>=l && t[k].r<=r) return t[k].sum; 53 pushdown(k);ll ans=0; 54 int mid=(t[k].l+t[k].r)>>1; 55 if(l<=mid) ans+=query(k<<1,l,r); 56 if(r>mid) ans+=query(k<<1|1,l,r); 57 return ans; 58 } 59 60 int main(){ 61 scanf("%d%d",&n,&m); 62 build(1,1,n); 63 for(int i=1;i<=m;i++){ 64 int p,x,y,z; 65 scanf("%d",&p); 66 if(p==1){ 67 scanf("%d%d%d",&x,&y,&z); 68 change(1,x,y,z); 69 } 70 else{ 71 scanf("%d%d",&x,&y); 72 cout<<query(1,x,y)<<endl; 73 } 74 } 75 return 0; 76 }
注意对一个节点打标记时,该区间内的元素已经被修改了,之后再下传标记。
标签:洛谷,标记,int,ll,long,build,lmid,P3372,模板 来源: https://www.cnblogs.com/yhxnoerror/p/16320238.html