[luoguP3373]线段树2

[luoguP3373]线段树2


1.我们规定先乘后加然后pushdown乘法的时候把加法一起乘就做出来了

坑:

1.pushup的时候忘了pushdown左右儿子,特别是add、mul操作中。
    *不能以为把add操作中的当前点都pushdown一遍就没有问题,
     有可能第一次操作在x<<1|1节点打标记然后下次操作你在x节点打标记,这样就会出问题
2.注意在判断出ql<=l&&qr>=r的时候return
3.注意ql,qr大部分时候是不用随着l,r改变的,我们直接判断当前段是否属于[ql,qr]即可
4.注意线段树要开到4N而不是2N,严格地说应该是开到2^(n+1),(2^n>=N),
  同时,如果是开到4N,下放标记的时候要判一下l,r,否则可能RE
  • 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+6;
typedef long long ll;
int n,m;
ll mod,a[N];
struct segtree{
    ll t[N*4],pl[N*4],cr[N*4];
    inline void build(int x,int l,int r){
        int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
        cr[x]=1;
        if(l==r){t[x]=a[mid];return;}
        build(lch,l,mid);
        build(rch,mid+1,r);
        t[x]=(t[lch]+t[rch])%mod;
    }
    inline void pushdown(int x,int l,int r){
        ll len=r-l+1;
        int lch=x<<1,rch=x<<1|1;
        if(cr[x]!=1){
            t[x]=t[x]*cr[x]%mod;
            if(l<r)cr[lch]=(cr[lch]*cr[x])%mod,pl[lch]=(pl[lch]*cr[x])%mod,pl[rch]=(pl[rch]*cr[x])%mod,cr[rch]=(cr[rch]*cr[x])%mod;
            cr[x]=1;
        }   
        if(pl[x]){
            t[x]=(t[x]+len*pl[x])%mod;
            if(l<r)pl[lch]=(pl[lch]+pl[x])%mod,pl[rch]=(pl[rch]+pl[x])%mod;
            pl[x]=0;
        }
    }
    inline void add(int x,int l,int r,int ql,int qr,ll sum){
        int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
        if(ql<=l&&qr>=r){
            pushdown(x,l,r);
            pl[x]=(pl[x]+sum)%mod;return;
        }
        pushdown(x,l,r);
        if(qr>mid) add(rch,mid+1,r,ql,qr,sum);
        if(ql<=mid) add(lch,l,mid,ql,qr,sum);
        pushdown(lch,l,mid);
        pushdown(rch,mid+1,r);
        t[x]=(t[lch]+t[rch])%mod;
    }
    inline void mul(int x,int l,int r,int ql,int qr,ll sum){
        int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
        if(ql<=l&&qr>=r){
            pushdown(x,l,r);
            cr[x]=cr[x]*sum%mod;return;
        }
        pushdown(x,l,r);
        if(qr>mid) mul(rch,mid+1,r,ql,qr,sum);
        if(ql<=mid) mul(lch,l,mid,ql,qr,sum);
        pushdown(lch,l,mid);
        pushdown(rch,mid+1,r);
        t[x]=(t[lch]+t[rch])%mod;
    }
    inline ll qry(int x,int l,int r,int ql,int qr){
        int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
        pushdown(x,l,r);
        if(ql<=l&&qr>=r){
            return t[x];
        }
        if(ql>mid)return qry(rch,mid+1,r,ql,qr);
        if(qr<=mid)return qry(lch,l,mid,ql,qr);
        return (qry(lch,l,mid,ql,qr)+qry(rch,mid+1,r,ql,qr))%mod;
    }
}T;

int main()
{
    scanf("%d%d%lld",&n,&m,&mod);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    T.build(1,1,n);
    while(m--){
        int opt,x,y;ll k;
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==1){
            scanf("%lld",&k);
            T.mul(1,1,n,x,y,k);
        }if(opt==2){
            scanf("%lld",&k);
            T.add(1,1,n,x,y,k);
        }if(opt==3){
            ll res=T.qry(1,1,n,x,y);
            printf("%lld\n",res);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/83017737