線段樹模板整理


   線段樹算是一種較為簡單的中級數據結構了,線段樹本身其實還是很簡單的,就是一棵二叉樹,每一個節點維護一塊區間的信息,如果根節點是$[1,n]$,那么左兒子就是$[1,n/2]$,右兒子就是$[n/2+1,n]$,如此二分下去就是一棵線段樹了,查找的時間復雜度是 $O\left ( \log_{2} N\right )$的,有圖為證:(網上找的)

線段樹

下面是某線段樹模板題的代碼:

#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\n",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\n",Query(1,l,r)%MOD);
73     }
74 
75     return 0;
76 }
View Code

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



線段樹模板整理 線段樹模板整理 【模板】線段樹模板 線段樹代碼整理 模板,線段樹,面積並 模板_zkw線段樹 線段樹模板(新) 【裸】線段樹模板 [線段樹]模板2 [模板] zkw線段樹
 
粤ICP备14056181号  © 2014-2020 ITdaan.com