zoukankan      html  css  js  c++  java
  • [板子]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
    ",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
    ",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的帮助

  • 相关阅读:
    hdu 4685(强连通分量+二分图的完美匹配)
    图的连通性问题
    poj 1904(强连通分量+完美匹配)
    poj 2186 "Popular Cows"(强连通分量入门题)
    poj 1236(强连通分量分解模板题)
    EOJ2018.10 月赛
    21.Merge Two Sorted Lists
    20.Valid Parentheses
    19.Remove Nth Node From End of List
    18.4Sum
  • 原文地址:https://www.cnblogs.com/Fylsea/p/7782730.html
Copyright © 2011-2022 走看看