其他分享
首页 > 其他分享> > 洛谷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 }

注意对一个节点打标记时,该区间内的元素已经被修改了,之后再下传标记。

标签:洛谷,标记,int,ll,long,build,lmid,P3372,模板
来源: https://www.cnblogs.com/yhxnoerror/p/16320238.html