线段树学习笔记(初级:只支持区间加、区间求和)

研究了很长时间线段树的理论,发现打过一遍代码就啥都懂了

简单来说,线段树是基于分治对区间进行快速修改的,所以时间效率很高

然后就是代码(洛谷太坑,query里面的ans也要开long long)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 const int N = 1e5 + 5;
 8 ll addv[N*4],sumv[N*4],a[N];
 9 int n,m;
10 inline int read()
11 {
12     int x=0,w=1; char c=getchar();
13     while (c>'9'|| c<'0') {if(c=='-') w=-1; c=getchar();}
14     while (c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar(); }
15     return w*x;
16 }
17 void pushup(int k)
18 {
19     sumv[k]=sumv[k<<1]+sumv[k<<1|1];
20 }
21 inline void build(int o,int l,int r)//建树
22 {
23     if (l==r) {sumv[o]=a[l]; return ;}
24     int mid=(l+r)>>1;//分治操作
25     build(o<<1,l,mid);
26     build(o<<1|1,mid+1,r);
27     pushup(o);
28 }
29 void pushdown(int o,int l,int r)//玄学的pushdown(由树上操作推导而来)
30 {
31     if (addv[o]==0) return ;
32     addv[o<<1]+=addv[o];
33     addv[o<<1|1]+=addv[o];
34     int mid= (l+r)>>1;
35     sumv[o<<1]+=addv[o]*(mid-l+1);
36     sumv[o<<1|1]+=addv[o]*(r-mid);
37     addv[o]=0;
38 }
39 void puttag(int o,int l,int r,ll v)//lazytag操作,懒标记
40 {
41     addv[o]+=v;
42     sumv[o]+=(r-l+1)*v;
43 }
44 void modify(int o,int l,int r,int ql,int qr,ll v)//区间修改
45 {
46     if (ql<=l&&qr>=r) {puttag(o,l,r,v); return ;}
47     int ans=0,mid=(l+r)>>1;
48     pushdown(o,l,r);//这里的pushdown不能忘了
49     if(ql<=mid) modify(o<<1,l,mid,ql,qr,v);
50     if(qr>mid) modify(o<<1|1,mid+1,r,ql,qr,v);
51     pushup(o);    
52 }
53 ll query(int o,int l,int r,int ql,int qr)//区间查询
54 {
55     if (ql<=l&&qr>=r) return sumv[o];
56     pushdown(o,l,r);
57     ll ans=0;
58     int mid=(l+r)>>1;
59     if (ql<=mid) ans+=query(o<<1,l,mid,ql,qr);
60     if (qr>mid) ans+=query(o<<1|1,mid+1,r,ql,qr);
61     return ans;
62 }
63 int main()
64 {
65     n=read(); m=read();    
66     for(int i=1;i<=n;++i)
67         scanf("%lld",&a[i]);
68     build(1,1,n);
69     while(m--)
70     {
71         int opt,l,r;
72         ll val;
73         opt=read();
74         if (opt==1) l=read(),r=read(),scanf("%lld",&val),modify(1,1,n,l,r,val);
75         else l=read(),r=read(),printf("%lld\n",query(1,1,n,l,r));
76     }
77     return 0;
78 }

To be continued...

猜你喜欢

转载自www.cnblogs.com/cptbtptpbcptbtptp/p/11605615.html