题解 P3373 【【模板】线段树 2】

· · 题解

思路跟楼下dalao公式一样 乘法分配率

记得乘法标签要膜!!!!!否则会爆

非指针代码如下

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#define ls (2*n)
#define rs (2*n+1)
#define mid ((l+r)/2)
#define LL long long
#include<cstring>
#include<stack>
using namespace std;
LL tree[1000000],a[1000000],lazy[1000000],tag[1000000];
LL x,y,k,mod,n,m;
void collect(LL n){tree[n]=tree[ls]+tree[rs];tree[n]%=mod;}
void pushdown(LL n,LL l,LL r)
{
    if(tag[n]!=1)
    {
        tree[ls]*=tag[n];tree[ls]%=mod;
        tree[rs]*=tag[n];tree[rs]%=mod;
        lazy[ls]*=tag[n];lazy[ls]%=mod;
        lazy[rs]*=tag[n];lazy[rs]%=mod;
        tag[ls]*=tag[n];tag[ls]%=mod;
        tag[rs]*=tag[n];tag[rs]%=mod;
        tag[n]=1;
    }
    if(lazy[n]!=0)
    {
        tree[ls]+=lazy[n]*(mid-l+1);tree[ls]%=mod;
        tree[rs]+=lazy[n]*(r-mid);tree[rs]%=mod;
        lazy[ls]+=lazy[n];lazy[ls]%=mod;
        lazy[rs]+=lazy[n];lazy[rs]%=mod;
        lazy[n]=0;
        return;
    }
    return;
}
void build(LL n,LL l,LL r)
{
   tag[n]=1;lazy[n]=0;
   if(l==r){tree[n]=a[l];return;}
   build(ls,l,mid);
   build(rs,mid+1,r);
   collect(n);
}
void multy(LL n,LL l,LL r,LL mul,LL mur,LL x)
{
    //printf("->%lld %lld %lld %lld\n",l,r,mul,mur);
    if(mul==l&&mur==r){lazy[n]*=x;lazy[n]%=mod;tag[n]*=x;tag[n]%=mod;tree[n]*=x;tree[n]%=mod;return;}
    pushdown(n,l,r);
    if(mur<=mid)multy(ls,l,mid,mul,mur,x);
    else if(mul>=mid+1)multy(rs,mid+1,r,mul,mur,x);
    else
    {
        multy(ls,l,mid,mul,mid,x);
        multy(rs,mid+1,r,mid+1,mur,x);
    }
    collect(n);
}
void add(LL n,LL l,LL r,LL addl,LL addr,LL x)
{
    if(addl==l&&addr==r){lazy[n]+=x;lazy[n]%=mod;tree[n]+=(r-l+1)*x;tree[n]%=mod;return;}
    pushdown(n,l,r);
    if(addr<=mid)add(ls,l,mid,addl,addr,x);
    else if(addl>=mid+1)add(rs,mid+1,r,addl,addr,x);
    else
    {
        add(ls,l,mid,addl,mid,x);
        add(rs,mid+1,r,mid+1,addr,x);
    }
    collect(n);
}
LL ask(LL n,LL l,LL r,LL askl,LL askr)
{
    if(askl==l&&askr==r)
    {
        return tree[n];
    }
    pushdown(n,l,r);
    LL res;
    if(askr<=mid)res=ask(ls,l,mid,askl,askr)%mod;
    else if(askl>=mid+1)res=ask(rs,mid+1,r,askl,askr)%mod;
    else
    {
        res=ask(ls,l,mid,askl,mid)%mod+ask(rs,mid+1,r,mid+1,askr)%mod;
    }
    return res%mod;
}
/*void print(LL n,LL l,LL r)
{
    printf("l:%lld r:%lld node:%lld tag:%lld lazy:%lld num:%lld\n",l,r,n,tag[n],lazy[n],tree[n]);
    if(l==r) return;
    print(ls,l,mid);
    print(rs,mid+1,r);
}*/
int main()
{
    cin>>n>>m>>mod;
    for(int i=1;i<=n;i++)cin>>a[i];
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int tmpa;
        cin>>tmpa;
        if(tmpa==1){cin>>x>>y>>k;multy(1,1,n,x,y,k);}
        else if(tmpa==2){cin>>x>>y>>k;add(1,1,n,x,y,k);}
        else {cin>>x>>y;cout<<ask(1,1,n,x,y)<<endl;}
        //print(1,1,n);
    }
}