• 线段树模板整理


       线段树算是一种较为简单的中级数据结构了,线段树本身其实还是很简单的,就是一棵二叉树,每一个节点维护一块区间的信息,如果根节点是$[1,n]$,那么左儿子就是$[1,n/2]$,右儿子就是$[n/2+1,n]$,如此二分下去就是一棵线段树了,查找的时间复杂度是 $Oleft ( log_{2} N ight )$的,有图为证:(网上找的)

    线段树

    下面是某线段树模板题的代码:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    static const int maxm=1e6+10;
    LL tree[maxm],lazy[maxm],A[maxm],left[maxm],right[maxm];
    int n,m;
    
    void build(int num,int l,int r){
        left[num]=l;right[num]=r;
        int mid=(l+r)>>1;
        if(l==r){ tree[num]=A[l]; return; }
        build(num<<1,l,mid);
        build(num<<1|1,mid+1,r);
        tree[num]=tree[num<<1]+tree[num<<1|1];
    }
    
    void pushdown(int num){
        if(lazy[num]){
            int mid=(left[num]+right[num])>>1;
            tree[num<<1]+=(mid-left[num]+1)*lazy[num];
            tree[num<<1|1]+=(right[num]-mid)*lazy[num];
            lazy[num<<1]+=lazy[num];
            lazy[num<<1|1]+=lazy[num];
            lazy[num]=0;
        }
    }
    
    void update(int num,int l,int r,LL add){
        if(left[num]>=l&&right[num]<=r){
            tree[num]+=(right[num]-left[num]+1)*add;
            lazy[num]+=add;
            return;
        }
        if(left[num]>r||right[num]<l)return;
        pushdown(num);
        update(num<<1,l,r,add);
        update(num<<1|1,l,r,add);
        tree[num]=tree[num<<1]+tree[num<<1|1];
    }
    
    LL Query(int num,int l,int r){
        if(left[num]>=l&&right[num]<=r)return tree[num];
        if(left[num]>r||right[num]<l) return 0;
        LL ret=0;
        pushdown(num);
        ret+=Query(num<<1,l,r);
        ret+=Query(num<<1|1,l,r);
        return ret;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
        build(1,1,n);
        for(int i=1;i<=m;i++){
            int f,x,y;LL add;
            scanf("%d",&f);
            switch(f){
                case 1:scanf("%d%d%lld",&x,&y,&add);update(1,x,y,add);break;
                case 2:scanf("%d%d",&x,&y);printf("%lld
    ",Query(1,x,y));break;
                default:printf("Orz %%%");break;
            }
        }
    
        return 0;
    }
    View Code

    以下是维护序列的代码:(滋瓷乘法运算)

     1 #include <cstdio>
     2 
     3 typedef long long LL;
     4 
     5 static const int maxm=100005;
     6 
     7 LL A[maxm],pls[maxm<<2],mul[maxm<<2],tr[maxm<<2];
     8 int left[maxm<<2],right[maxm<<2];
     9 int n,m;
    10 LL MOD;
    11 
    12 int build(int id,int l,int r){
    13     left[id]=l;right[id]=r;mul[id]=1;
    14     if(l==r)return tr[id]=A[l]%MOD,0;
    15     int mid=(l+r)>>1;
    16     build(id<<1,l,mid);
    17     build(id<<1|1,mid+1,r);
    18     tr[id]=(tr[id<<1]+tr[id<<1|1])%MOD;
    19 }
    20 
    21 void pushdown(int id){
    22     int l=left[id];int r=right[id];int mid=(l+r)>>1;
    23     pls[id<<1]=(pls[id<<1]*mul[id]%MOD+pls[id])%MOD;
    24     pls[id<<1|1]=(pls[id<<1|1]*mul[id]%MOD+pls[id])%MOD;
    25     mul[id<<1]=(mul[id]*mul[id<<1])%MOD;
    26     mul[id<<1|1]=(mul[id]*mul[id<<1|1])%MOD;
    27     tr[id<<1]=(tr[id<<1]*mul[id]%MOD+pls[id]*(mid-l+1)%MOD)%MOD;
    28     tr[id<<1|1]=(tr[id<<1|1]*mul[id]%MOD+pls[id]*(r-mid)%MOD)%MOD;
    29     mul[id]=1;pls[id]=0;
    30 }
    31 
    32 void modify(int id,int l,int r,int c,int opt){
    33     if(left[id]>=l&&right[id]<=r){
    34         if(opt==1){
    35             mul[id]=(mul[id]*c)%MOD;
    36             pls[id]=(pls[id]*c)%MOD;
    37             tr[id]=(tr[id]*c)%MOD;
    38         }else if(opt==2){
    39             pls[id]=(pls[id]+c)%MOD;
    40             tr[id]=(tr[id]+(LL)c*(right[id]-left[id]+1)%MOD)%MOD;
    41         }
    42         return ;
    43     }
    44     if(right[id]<l||left[id]>r)return ;
    45     pushdown(id);
    46     modify(id<<1,l,r,c,opt);
    47     modify(id<<1|1,l,r,c,opt);
    48     tr[id]=(tr[id<<1]+tr[id<<1|1])%MOD;
    49 }
    50 
    51 LL Query(int id,int l,int r){
    52     if(left[id]>=l&&right[id]<=r)return tr[id]%MOD;
    53     if(left[id]>r||right[id]<l)return 0;
    54     pushdown(id);
    55     return (Query(id<<1,l,r)%MOD+Query(id<<1|1,l,r)%MOD)%MOD;
    56 }
    57 
    58 int main(){
    59     int opt,l,r,c;
    60     scanf("%d%lld",&n,&MOD);
    61     for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
    62     scanf("%d",&m);
    63 
    64     build(1,1,n);
    65     
    66     while(m--){
    67         scanf("%d",&opt);
    68         if(opt!=3){
    69             scanf("%d%d%d",&l,&r,&c);
    70             modify(1,l,r,c,opt);
    71         }
    72         else scanf("%d%d",&l,&r),printf("%lld
    ",Query(1,l,r)%MOD);
    73     }
    74 
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    「BZOJ1954」Pku3764 The xor – longest Path
    【bzoj4260】【Codechef REBXOR】
    BZOJ_3012_[Usaco2012 Dec]First!
    【bzoj1174】[Balkan2007]Toponyms
    String
    前缀和
    [POI2008] CLO
    [Scoi2010] 游戏
    CodeForces892E
    并查集的删除操作
  • 原文地址:https://www.cnblogs.com/Exbilar/p/6388902.html
Copyright © 2020-2023  润新知