1. 程式人生 > 其它 >洛谷P3372 【模板】線段樹 1

洛谷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 }

注意對一個節點打標記時,該區間內的元素已經被修改了,之後再下傳標記。