自用综合线段树模板(区间加乘区间置数区间求和)

Posted mmasker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自用综合线段树模板(区间加乘区间置数区间求和)相关的知识,希望对你有一定的参考价值。

ll p,a[MAXN],atag[MAXN],mtag[MAXN],ctag[MAXN],tree[MAXN];

void Pushup(int rt){tree[rt]=(tree[rt<<1]+tree[rt<<1|1])%p;}

void Pushdown(int rt,int ln,int rn){
    if(ctag[rt]!=-1){
        ctag[rt<<1]=ctag[rt<<1|1]=ctag[rt];
        tree[rt<<1]=ctag[rt]*ln%p;
        tree[rt<<1|1]=ctag[rt]*rn%p;
        atag[rt<<1]=atag[rt<<1|1]=0;
        mtag[rt<<1]=mtag[rt<<1|1]=1;
        ctag[rt]=-1;
    }
    if(mtag[rt]!=1){
        mtag[rt<<1]=(mtag[rt<<1]*mtag[rt])%p;
        mtag[rt<<1|1]=(mtag[rt<<1|1]*mtag[rt])%p;
        atag[rt<<1]=(atag[rt<<1]*mtag[rt])%p;
        atag[rt<<1|1]=(atag[rt<<1|1]*mtag[rt])%p;
        tree[rt<<1]=(tree[rt<<1]*mtag[rt])%p;
        tree[rt<<1|1]=(tree[rt<<1|1]*mtag[rt])%p;
        mtag[rt]=1;
    }
    if(atag[rt]){
        atag[rt<<1]=(atag[rt<<1]+atag[rt])%p;
        atag[rt<<1|1]=(atag[rt<<1|1]+atag[rt])%p;
        tree[rt<<1]=(tree[rt<<1]+atag[rt]*ln)%p;
        tree[rt<<1|1]=(tree[rt<<1|1]+atag[rt]*rn)%p;
        atag[rt]=0;
    }
}

void Build(int l,int r,int rt){
    atag[rt]=0; ctag[rt]=-1; mtag[rt]=1;
    if(l==r){
        tree[rt]=a[l]%p;
        return ;
    }
    int mid=(l+r)/2;
    Build(ls);
    Build(rs);
    Pushup(rt);
}

void Add(int L,int R,int C,int l,int r,int rt){
    if(L<=l&&R>=r){
        tree[rt]=(tree[rt]+1ll*C*(r-l+1))%p;
        atag[rt]=(atag[rt]+C)%p;
        return ;
    }
    int mid=(l+r)/2;
    Pushdown(rt,mid-l+1,r-mid);
    if(L<=mid)Add(L,R,C,ls);
    if(R>mid)Add(L,R,C,rs);
    Pushup(rt);
}

void Mul(int L,int R,int C,int l,int r,int rt){
    if(L<=l&&R>=r){
        tree[rt]=tree[rt]*C%p;
        atag[rt]=atag[rt]*C%p;
        mtag[rt]=mtag[rt]*C%p;
        return ;
    }
    int mid=(l+r)/2;
    Pushdown(rt,mid-l+1,r-mid);
    if(L<=mid)Mul(L,R,C,ls);
    if(R>mid)Mul(L,R,C,rs);
    Pushup(rt);
}


void Change(int L,int R,int C,int l,int r,int rt){
    if(L<=l&&R>=r){
        tree[rt]=1ll*(r-l+1)*C%p;
        ctag[rt]=C%p;
        atag[rt]=0;
        mtag[rt]=1;
        return ;
    }
    int mid=(l+r)/2;
    Pushdown(rt,mid-l+1,r-mid);
    if(L<=mid)Change(L,R,C,ls);
    if(R>mid)Change(L,R,C,rs);
    Pushup(rt);
}

ll Query(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r)return tree[rt]%p;
    int mid=(l+r)/2;
    Pushdown(rt,mid-l+1,r-mid);
    ll ans=0;
    if(L<=mid)ans=(ans+Query(L,R,ls))%p;
    if(R>mid)ans=(ans+Query(L,R,rs))%p;
    return ans;
}

 

以上是关于自用综合线段树模板(区间加乘区间置数区间求和)的主要内容,如果未能解决你的问题,请参考以下文章

Luogu 3373 - 模板线段树 2 - [加乘线段树]

「模板」 线段树——区间乘 && 区间加 && 区间求和

线段树模板——区间乘 && 区间加 && 区间求和

P3373 模板线段树 2 区间求和 区间乘 区间加

POJ 3468 A Simple Problem with Integers(线段树模板之区间增减更新 区间求和查询)

树链剖分+线段树 单点修改 区间求和 模板