[板子]segTree
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[板子]segTree相关的知识,希望对你有一定的参考价值。
segTree
参考:http://www.cnblogs.com/TenosDoIt/p/3453089.html#c
初学者建议先参考上面“一步一步理解线段树”学习理论。
在这里Code分别为区间求和&区间求积的做法。
分别对应OJ luogu的3372和3373
1.区间和
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 struct node{ 7 long long val,lazytag; 8 }segTree[100000*4+5]; 9 long long a[100005]; 10 int n,m,t,x,y,k; 11 void build(int root,long long arr[],int istart,int iend){//建树 12 segTree[root].lazytag=0; 13 if(istart==iend){ 14 segTree[root].val=arr[istart]; 15 }else{ 16 int mid=(istart+iend)/2; 17 build(root*2,arr,istart,mid); 18 build(root*2+1,arr,mid+1,iend); 19 segTree[root].val=segTree[root*2].val+segTree[root*2+1].val; 20 } 21 } 22 void pushDown(int root,int start,int end){//插入懒标记 23 if(segTree[root].lazytag!=0){ 24 segTree[root*2].lazytag+=segTree[root].lazytag; 25 segTree[root*2+1].lazytag+=segTree[root].lazytag; 26 int mid=(end+start)/2; 27 segTree[root*2].val+=segTree[root].lazytag*(mid-start+1); 28 segTree[root*2+1].val+=segTree[root].lazytag*(end-mid); 29 segTree[root].lazytag=0; 30 } 31 } 32 long long query(int root,int nstart,int nend,int qstart,int qend){//查询区间 33 if(qstart>nend||qend<nstart){ 34 return 0; 35 }if(qstart<=nstart&&qend>=nend){ 36 return segTree[root].val; 37 } 38 pushDown(root,nstart,nend); 39 int mid=(nstart+nend)/2; 40 return query(root*2,nstart,mid,qstart,qend)+query(root*2+1,mid+1,nend,qstart,qend); 41 } 42 void update(int root,int nstart,int nend,int ustart,int uend,int addval){//赋值 43 if(ustart>nend||uend<nstart){ 44 return; 45 }if(ustart<=nstart&&uend>=nend){ 46 segTree[root].lazytag+=addval; 47 segTree[root].val+=addval*(nend-nstart+1); 48 return; 49 } 50 pushDown(root,nstart,nend); 51 int mid=(nstart+nend)/2; 52 update(root*2,nstart,mid,ustart,uend,addval); 53 update(root*2+1,mid+1,nend,ustart,uend,addval); 54 segTree[root].val=segTree[root*2].val+segTree[root*2+1].val; 55 } 56 int main(){ 57 scanf("%lld%lld",&n,&m); 58 for(int i=1;i<=n;i++){ 59 scanf("%lld",&a[i]); 60 } 61 build(1,a,1,n); 62 for(int i=1;i<=m;i++){ 63 scanf("%lld",&t); 64 if(t==1){ 65 scanf("%lld%lld%lld",&x,&y,&k); 66 update(1,1,n,x,y,k); 67 }if(t==2){ 68 scanf("%lld%lld",&x,&y); 69 printf("%lld\\n",query(1,1,n,x,y)); 70 } 71 } 72 }
2.区间积
在这里要点几个点注意:
1:tag2的初始值为1;
2:pushdown里先tag2后tag1(先乘后加);
3:对tag2进行push需要先把tag1*tag2,tag2*tag2,val*tag2,最后别忘了tag2=1;
4:tag2不需要乘区间,原因是:a*(b+c)=a*b+a*c,乘法分配律;
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 struct node{ 7 long long val,lazytag,lazytag2; 8 }segTree[100000*4+5]; 9 long long a[100005]; 10 long long n,m,t,x,y,k,p; 11 void build(int root,long long arr[],int istart,int iend){//建树 12 segTree[root].lazytag=0; 13 segTree[root].lazytag2=1; 14 if(istart==iend){ 15 segTree[root].val=arr[istart]; 16 }else{ 17 int mid=(istart+iend)/2; 18 build(root*2,arr,istart,mid); 19 build(root*2+1,arr,mid+1,iend); 20 segTree[root].val=segTree[root*2].val+segTree[root*2+1].val; 21 } 22 } 23 void pushDown(int root,int start,int end){//插入懒标记 24 **if(segTree[root].lazytag2!=1){** 25 segTree[root*2].lazytag=(segTree[root*2].lazytag*segTree[root].lazytag2)%p; 26 segTree[root*2+1].lazytag=(segTree[root*2+1].lazytag*segTree[root].lazytag2)%p; 27 segTree[root*2].lazytag2=(segTree[root*2].lazytag2*segTree[root].lazytag2)%p; 28 segTree[root*2+1].lazytag2=(segTree[root*2+1].lazytag2*segTree[root].lazytag2)%p; 29 int midd=(end+start)/2; 30 segTree[root*2].val=(segTree[root*2].val*(segTree[root].lazytag2))%p; 31 segTree[root*2+1].val=(segTree[root*2+1].val*(segTree[root].lazytag2))%p; 32 segTree[root].lazytag2=1; 33 } 34 if(segTree[root].lazytag!=0){ 35 segTree[root*2].lazytag+=segTree[root].lazytag; 36 segTree[root*2+1].lazytag+=segTree[root].lazytag; 37 int mid=(end+start)/2; 38 segTree[root*2].val+=segTree[root].lazytag*(mid-start+1); 39 segTree[root*2+1].val+=segTree[root].lazytag*(end-mid); 40 segTree[root].lazytag=0; 41 } 42 } 43 long long query(int root,int nstart,int nend,int qstart,int qend){//查询区间 44 if(qstart>nend||qend<nstart){ 45 return 0; 46 }if(qstart<=nstart&&qend>=nend){ 47 return segTree[root].val; 48 } 49 pushDown(root,nstart,nend); 50 int mid=(nstart+nend)/2; 51 return query(root*2,nstart,mid,qstart,qend)+query(root*2+1,mid+1,nend,qstart,qend); 52 } 53 void update(int root,int nstart,int nend,int ustart,int uend,int addval){//赋值 54 if(ustart>nend||uend<nstart){ 55 return; 56 }if(ustart<=nstart&&uend>=nend){ 57 segTree[root].lazytag+=addval; 58 segTree[root].val+=addval*(nend-nstart+1); 59 return; 60 } 61 pushDown(root,nstart,nend); 62 int mid=(nstart+nend)/2; 63 update(root*2,nstart,mid,ustart,uend,addval); 64 update(root*2+1,mid+1,nend,ustart,uend,addval); 65 segTree[root].val=segTree[root*2].val+segTree[root*2+1].val; 66 } 67 **void tupdate(int root,int nstart,int nend,int ustart,int uend,int addval){//赋值(chengfa** 68 if(ustart>nend||uend<nstart){ 69 return; 70 }if(ustart<=nstart&&uend>=nend){ 71 segTree[root].lazytag=(segTree[root].lazytag*addval)%p; 72 segTree[root].lazytag2=(segTree[root].lazytag2*addval)%p; 73 segTree[root].val=(segTree[root].val*addval)%p; 74 return; 75 } 76 pushDown(root,nstart,nend); 77 int mid=(nstart+nend)/2; 78 tupdate(root*2,nstart,mid,ustart,uend,addval); 79 tupdate(root*2+1,mid+1,nend,ustart,uend,addval); 80 segTree[root].val=segTree[root*2].val+segTree[root*2+1].val; 81 } 82 int main(){ 83 scanf("%lld%lld%lld",&n,&m,&p); 84 for(int i=1;i<=n;i++){ 85 scanf("%lld",&a[i]); 86 } 87 build(1,a,1,n); 88 for(int i=1;i<=m;i++){ 89 scanf("%lld",&t); 90 if(t==2){ 91 scanf("%lld%lld%lld",&x,&y,&k); 92 update(1,1,n,x,y,k); 93 }if(t==3){ 94 scanf("%lld%lld",&x,&y); 95 printf("%lld\\n",query(1,1,n,x,y)%p); 96 }if(t==1){ 97 scanf("%lld%lld%lld",&x,&y,&k); 98 tupdate(1,1,n,x,y,k); 99 } 100 } 101 return 0; 102 }
并且感谢will7101的帮助
以上是关于[板子]segTree的主要内容,如果未能解决你的问题,请参考以下文章