天天看点

线段树相关

模板链接:

支持区间加减,乘。询问区间和。

要注意的几点:

1.输出格式!!!!

2.$printf("")$语法要写对,不然的话能过编辑,半天调不出来。

3.位运算的时候$>>1$和$<<1$和$<<1|1$分清……

4.将什么$val[p]+=……,val[p]%=mod$ 要写到一句的时候,一定要记得$val[p]=val[p]+……$,不是$val[p]=……$

好了,这$4$点调了一上午$……$

代码奉上

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int mod;
struct linetree{
    long long val[400010];
    long long lazyp[400010];
    long long lazym[400010];
    inline void update(int p,int l,int r)
    {
        val[p]=(val[p]*lazym[p])%mod,
        val[p]=(val[p]+(r-l)*lazyp[p])%mod;
        return ;
    }
    inline void pushdown(int p,int l,int r)
    {
        update(p,l,r);
        if(r-l>1)
        {
            lazyp[p<<1]=(lazyp[p<<1]*lazym[p]+lazyp[p])%mod,
            lazym[p<<1]=(lazym[p<<1]*lazym[p])%mod;
            lazyp[p<<1|1]=(lazyp[p<<1|1]*lazym[p]+lazyp[p])%mod,
            lazym[p<<1|1]=(lazym[p<<1|1]*lazym[p])%mod;            
        }lazyp[p]=0,lazym[p]=1;

        return ;
    }
    inline int build(int p,int l,int r)
    {
        lazym[p]=1;
        if(r-l==1) {scanf("%lld",&val[p]),val[p]%=mod;return val[p];}
        int mid=l+r>>1;
        if(mid>l) val[p]=(val[p]+build(p<<1,l,mid))%mod;
        if(mid<r) val[p]=(val[p]+build(p<<1|1,mid,r))%mod;
        return val[p];
    }
    void setpluse(int p,int l,int r,int dl,int dr,long long pluse)
    {
        if(lazyp[p]!=0||lazym[p]!=1) pushdown(p,l,r);
        if(l==dl&&r==dr){lazyp[p]=(lazyp[p]+pluse)%mod,pushdown(p,l,r);return ;}
        int mid=l+r>>1;
        if(mid>dl) setpluse(p<<1,l,mid,dl,min(mid,dr),pluse);else pushdown(p<<1,l,mid);
        if(mid<dr) setpluse(p<<1|1,mid,r,max(dl,mid),dr,pluse);else pushdown(p<<1|1,mid,r);
        val[p]=val[p<<1]+val[p<<1|1];
        return ;
    }
    void setmulty(int p,int l,int r,int dl,int dr,long long multy)
    {
        if(lazyp[p]!=0||lazym[p]!=1) pushdown(p,l,r);
        if(l==dl&&r==dr)
        {lazyp[p]=(lazyp[p]*multy)%mod,lazym[p]=(lazym[p]*multy)%mod,pushdown(p,l,r);return ;}
        int mid=l+r>>1;
        if(mid>dl) setmulty(p<<1,l,mid,dl,min(mid,dr),multy);else pushdown(p<<1,l,mid);
        if(mid<dr) setmulty(p<<1|1,mid,r,max(dl,mid),dr,multy);else pushdown(p<<1|1,mid,r);
        val[p]=(val[p<<1]+val[p<<1|1])%mod;
        return ;
    }
    int sum(int p,int l,int r,int dl,int dr)
    {
        if(lazyp[p]!=0||lazym[p]!=1) pushdown(p,l,r);
        if(l==dl&&r==dr) return val[p];
        int mid=l+r>>1;int res=0;
        if(mid>dl) res+=sum(p<<1,l,mid,dl,min(dr,mid));
        if(mid<dr) res+=sum(p<<1|1,mid,r,max(dl,mid),dr);
        res%=mod;
        return res;
    }

}lt;
int n,m,t;
int u,v,opt;
signed main()
{
    scanf("%d%d%d",&n,&m,&mod);
    lt.build(1,0,n);
    for(int i=1;i<=m;i++)
    {

        scanf("%d%d%d",&opt,&u,&v);
        if(opt==1) {scanf("%d",&t);lt.setmulty(1,0,n,u-1,v,t);}
        if(opt==2) {scanf("%d",&t);lt.setpluse(1,0,n,u-1,v,t);}
        if(opt==3) {printf("%d\n",lt.sum(1,0,n,u-1,v));}
    }
    return 0;
}