[板子]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的主要内容,如果未能解决你的问题,请参考以下文章

kuangbin_SegTree D (POJ 2528)

线段树 P3373

COGS 2554. [福利]可持久化线段树

AC日记——[福利]可持久化线段树 cogs 2554

nRF52832的板子,我想让LED2亮怎么写代码

树状数组板子