线段树乘法取%版

没什么好说的0.0,直接贴代码。

#include<bits/stdc++.h>
using namespace std;

const int MAXN=100005;

long long a[MAXN];
long long sumv[MAXN<<2],lzt[MAXN<<2],sst[MAXN<<2];
long long mod;
struct xds{
#define lson (o<<1)
#define rson (o<<1|1)
#define mid  ((l+r)>>1)
inline void pushdown(int o,int l,int r){
    if(sst[o]!=1){
        lzt[lson]=(lzt[lson]*sst[o])%mod;lzt[rson]=(lzt[rson]*sst[o])%mod;
        sumv[lson]=sumv[lson]*sst[o]%mod;sumv[rson]=sumv[rson]*sst[o]%mod;
        sst[lson]=sst[lson]*sst[o]%mod;sst[rson]=sst[rson]*sst[o]%mod;
        sst[o]=1;
    }
        if(lzt[o]){
        sumv[lson]=(sumv[lson]+((mid-l+1)*lzt[o]))%mod;sumv[rson]=(sumv[rson]+((r-mid)*lzt[o]))%mod;
        lzt[lson]=(lzt[lson]+lzt[o])%mod;lzt[rson]=(lzt[rson]+lzt[o])%mod;
        lzt[o]=0;
    }
}
inline void pushup(int o){sumv[o]=(sumv[lson]+sumv[rson])%mod;}
inline void buildt(int o,int l,int r){
    lzt[o]=0;
    sst[o]=1;
    if(l==r){sumv[o]=a[l];return;}
    buildt(lson,l,mid);
    buildt(rson,mid+1,r);
    pushup(o);
}
inline long long query(int o,int l,int r,int ql,int qr){
    if(ql<=l&&qr>=r){return sumv[o];}
    long long ans=0;
    pushdown(o,l,r);
    if(ql<=mid)ans=(ans+query(lson,l,mid,ql,qr))%mod;
    if(qr>mid)ans=(ans+query(rson,mid+1,r,ql,qr))%mod;
    return ans%mod;
}
inline void add(int o,int l,int r,int ql,int qr,long long v){
    if(ql<=l&&qr>=r){sumv[o]=(sumv[o]+(r-l+1)*v)%mod;lzt[o]=(lzt[o]+v)%mod;return;}
    pushdown(o,l,r);
    if(ql<=mid)add(lson,l,mid,ql,qr,v);
    if(qr>mid)add(rson,mid+1,r,ql,qr,v);
    pushup(o);
}
inline void mut(int o,int l,int r,int ql,int qr,long long v){
    if(ql<=l&&qr>=r){lzt[o]=(lzt[o]*v)%mod;sumv[o]=sumv[o]*v%mod;sst[o]=sst[o]*v%mod;return;}
    pushdown(o,l,r);
    if(ql<=mid)mut(lson,l,mid,ql,qr,v);
    if(qr>mid)mut(rson,mid+1,r,ql,qr,v);
    pushup(o);
}

};

int n,m,tem,tem1,tem2;
long long tem4;
int main(){
xds wa;
scanf("%d%d%d",&n,&m,&mod);
for(int i=1;i<=n;i++){
    scanf("%lld",&a[i]);
}
wa.buildt(1,1,n);
for(int i=1;i<=m;i++){
    scanf("%d",&tem);
    if(tem==1){
        scanf("%d%d%lld",&tem1,&tem2,&tem4);
        wa.mut(1,1,n,tem1,tem2,tem4);
    }
    if(tem==2){
        scanf("%d%d%lld",&tem1,&tem2,&tem4);
        wa.add(1,1,n,tem1,tem2,tem4);
    }
    if(tem==3){
        scanf("%d%d",&tem1,&tem2);
        cout<<wa.query(1,1,n,tem1,tem2)<<endl;
    }
}
return 0; 

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值