[模板] 线段树

最规整的版本。
玩火需谨慎(&)

//Writer:GhostCai && His Yellow Duck

#include<iostream>
using namespace std;

const long long MAXN=200005;

long long n,m;
long long a[MAXN];

struct Node{
    long long sum;
    long long ls,rs,l,r;
    long long lazy;
}node[MAXN];
long long cnt,root;

void pushup(long long now){
    Node &o=node[now];
    Node &nl=node[o.ls],&nr=node[o.rs];
    o.sum = nl.sum + nr.sum ;
    o.l = nl.l ;
    o.r = nr.r ;
}

void pushdown(long long now){
    Node &o=node[now];
    Node &nl=node[o.ls],&nr=node[o.rs];
    nl.lazy +=o.lazy ;
    nr.lazy +=o.lazy ;
    nl.sum +=o.lazy *(nl.r-nl.l+1);
    nr.sum +=o.lazy *(nr.r-nr.l+1);
    o.lazy = 0;
}

void build(long long L,long long R,long long now){
    Node &o=node[now]; 
    if(L==R){
        o.sum = a[L];
        o.ls = o.rs =-1;
        o.l = o.r = L;
        return ;
    }
    long long mid=(L+R)>>1;
    build(L,mid,o.ls=cnt++);
    build(mid+1,R,o.rs=cnt++);
    pushup(now);
}

long long query(long long L,long long R,long long now){
    Node &o=node[now];
    Node &nl=node[o.ls],&nr=node[o.rs];
    if(L<=o.l&&o.r<=R) return o.sum ;
    pushdown(now);
    long long mid=(o.l +o.r )>>1;
    long long sum=0;
    if(L<=mid) sum+=query(L,R,o.ls);
    if(mid<R)  sum+=query(L,R,o.rs);
    return sum;
}

void updata(long long L,long long R,long long w,long long now){
    Node &o=node[now];
    Node &nl=node[o.ls],&nr=node[o.rs];
    if(L<=o.l&&o.r<=R){
        o.sum +=w*(o.r-o.l+1);
        o.lazy +=w;
        return ;
    }
    pushdown(now);
    long long mid=(o.l+o.r)>>1;
    if(L<=mid) updata(L,R,w,o.ls);
    if(mid< R) updata(L,R,w,o.rs);
    pushup(now); 
}

int main(){
    cin>>n>>m;
    for(long long i=1;i<=n;i++) cin>>a[i];
    build(1,n,root=cnt++);
    long long q,x,y,z;
    for(long long i=1;i<=m;i++){
        cin>>q;
        if(q==1){
            cin>>x>>y>>z;
            updata(x,y,z,root);
        }else{
            cin>>x>>y;
            cout<<query(x,y,root)<<endl;
        }
    }
}

好写的版本

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#define ls now<<1
#define rs now<<1|1
using namespace std;

const int MAXN=200000;

int val[MAXN],lazy[MAXN];
int a[MAXN]; 
void pushup(int now){
    val[now]=val[ls]+val[rs];
}

void pushdown(int now,int l,int r){
    int mid=(l+r)>>1;
    lazy[ls]+=lazy[now];
    lazy[rs]+=lazy[now];
    val[ls]+=lazy[now]*(mid-l+1);
    val[rs]+=lazy[now]*(r-mid); 
    lazy[now]=0;
}

void build(int L,int R,int now){
    if(L==R){
        val[now]=a[L];// 
        return ;
    }
    int mid=(L+R)>>1;
    build(L,mid,ls);
    build(mid+1,R,rs);
    pushup(now);
}

void updata(int L,int R,int l,int r,int now,int w){
    if(L<=l&&r<=R){
        lazy[now]+=w;
        val[now]+=w*(r-l+1);
        return ; 
    }
    pushdown(now,l,r);
    int mid=(l+r)>>1;
    if(L<=mid) updata(L,R,l,mid,ls,w);
    if(mid <R) updata(L,R,mid+1,r,rs,w);
    pushup(now);
}

int query(int L,int R,int l,int r,int now){
    if(L<=l&&r<=R){
        return val[now];
    }
    int mid=(l+r)>>1;
    int ret=0;
    pushdown(now,l,r);
    if(L<=mid) ret+=query(L,R,l,mid,ls);
    if(mid <R) ret+=query(L,R,mid+1,r,rs);
    return ret;
}

int n,m;

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    build(1,n,1);
    for(int i=1;i<=m;i++){
        int q,x,y,z;
        cin>>q;
        if(q==1){
            cin>>x>>y>>z;
            updata(x,y,1,n,1,z);
        }else{
            cin>>x>>y;
            cout<<query(x,y,1,n,1)<<endl;
        }
    }
    return 0;
}

乘法标记+封装

#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;

const int MAXN=300005;

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

int p;

struct Seg{
    #define ls now<<1
    #define rs now<<1|1
    #define mid ((l+r)>>1)

    int sum[MAXN],add[MAXN],mut[MAXN],a[MAXN];

    void pushup(int now){sum[now]=sum[ls]+sum[rs];}

    void pushdown(int now,int l,int r){
        mut[now]%=p;add[now]%=p;
        mut[ls]*=mut[now];mut[ls]%=p;
        mut[rs]*=mut[now];mut[rs]%=p;
        add[ls]=add[ls]*mut[now]+add[now];
        add[rs]=add[rs]*mut[now]+add[now];
        sum[ls]=sum[ls]*mut[now]+(mid-l+1)*add[now];
        sum[rs]=sum[rs]*mut[now]+(r-mid)*add[now];
        add[ls]%=p;add[rs]%=p;sum[ls]%=p;sum[rs]%=p;
        add[now]=0;mut[now]=1;
    }

    void build(int now,int l,int r){
        if(l==r){sum[now]=a[l];mut[now]=1;return;}
        build(ls,l,mid);
        build(rs,mid+1,r);
        mut[now]=1;//
        pushup(now);
    }

    void updata_mut(int L,int R,int w,int now,int l,int r){
        if(L<=l&&r<=R){sum[now]*=w;sum[now]%=p;mut[now]*=w;mut[now]%=p;add[now]*=w;add[now]%=p;return;}
        pushdown(now,l,r);
        if(L<=mid) updata_mut(L,R,w,ls,l,mid);
        if(mid <R) updata_mut(L,R,w,rs,mid+1,r);
        pushup(now);
    }

    void updata_add(int L,int R,int w,int now,int l,int r){
        if(L<=l&&r<=R){sum[now]+=w*(r-l+1);sum[now]%=p;add[now]+=w;add[now]%=p;return;}
        pushdown(now,l,r);
        if(L<=mid) updata_add(L,R,w,ls,l,mid);
        if(mid <R) updata_add(L,R,w,rs,mid+1,r);
        pushup(now);
    }

    int query(int L,int R,int now,int l,int r){
        if(L<=l&&r<=R){return sum[now];}
        pushdown(now,l,r);
        int ret=0;
        if(L<=mid) ret+=query(L,R,ls,l,mid),ret%=p;
        if(mid <R) ret+=query(L,R,rs,mid+1,r),ret%=p;
        return ret%p;
    }
}t;

int n,m;

signed main(){
    n=rd();m=rd();p=rd();
    for(int i=1;i<=n;i++) t.a[i]=rd();
    t.build(1,1,n);
    for(int i=1;i<=m;i++){
        int x,y,w,q;
        q=rd();
        switch(q){
            case 1:{
                x=rd();y=rd();w=rd();
                t.updata_mut(x,y,w%p,1,1,n);
                break;
            }
            case 2:{
                x=rd();y=rd();w=rd();
                t.updata_add(x,y,w%p,1,1,n);
                break;
            }
            case 3:{
                x=rd();y=rd();
                printf("%d
",t.query(x,y,1,1,n));
                break;
            }
        }
    }
    return 0;
}

本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247488.html

原文地址:https://www.cnblogs.com/ghostcai/p/9247488.html