2019.9.8 线段树模板

 1 // luogu-judger-enable-o2
 2 #include <cstdio>
 3 using namespace std;
 4 const int N=1e5+5;
 5 long long tree[4*N],a[N],m,n,x,y,z,d,lazy[4*N];//一般数组开成数据范围N的4倍
 6 void pushdown(int P,int l,int r)//lazy标记下传
 7 {
 8     int mid=(l+r)>>1;
 9     tree[P*2]+=(mid-l+1)*lazy[P];
10     lazy[P*2]+=lazy[P];
11     tree[P*2+1]+=(r-mid)*lazy[P];
12     lazy[P*2+1]+=lazy[P];
13     lazy[P]=0;
14 }
15 void buildtree(int P,/*编号*/int l,/**/int r/**/)//对于节点编号P两个子节点编为P*2,P*2+1 
16 {
17     if(l==r) {tree[P]=a[l]; return ;}
18     int mid=(l+r)/2;
19     buildtree(P*2,l,mid);
20     buildtree(P*2+1,mid+1,r);
21     tree[P]=tree[P*2]+tree[P*2+1];
22 }//建树 已理解
23 void modifytree(int P,int l,int r,int ll,int rr,int x)//ll到rr加上x ;ll\rr为被修改区间的左右端点 
24 {
25     if(l==ll&&r==rr) {tree[P]+=x*(r-l+1);lazy[P]+=x;/*lazy标记*/ return;}
26     pushdown(P,l,r);
27     int mid=(l+r)/2;
28     if(ll>mid) modifytree(P*2+1,mid+1,r,ll,rr,x);
29     else if(mid>=rr) modifytree(P*2,l,mid,ll,rr,x);
30     else modifytree(P*2,l,mid,ll,mid,x),modifytree(P*2+1,mid+1,r,mid+1,rr,x);
31     tree[P]=tree[P*2]+tree[P*2+1];
32 }
33 long long asktree/*询问*/(int P,int l,int r,int askl,int askr)
34 //在编号为P,范围是l到r的线段中,找到askl到askr这一段 
35 {
36     int mid=(l+r)/2;
37     if(l==askl && r==askr) return tree[P];
38     if(lazy[P]!=0) {
39         pushdown(P,l,r);}
40     
41     if(mid>=askr) return asktree(P*2,l,mid,askl,askr) ;
42     else if(mid<askl) return asktree(P*2+1,mid+1,r,askl,askr);
43     return asktree(P*2,l,mid,askl,mid)+asktree(P*2+1,mid+1,r,mid+1,askr);
44     
45 }
46 int main()
47 {
48     scanf("%lld %lld",&n,&m);
49     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
50     buildtree(1,1,n);
51     //scanf("%d",&m);
52     for(int i=1;i<=m;i++)
53     {
54     scanf("%lld",&x);
55     if(x==1) scanf("%lld %lld %lld",&y,&z,&d),modifytree(1,1,n,y,z,d);
56     if(x==2) scanf("%lld %lld",&y,&z),printf("%lld\n",asktree(1,1,n,y,z));
57     }
58     return 0; 
59 }

猜你喜欢

转载自www.cnblogs.com/liuziwen0224/p/tree1.html