线段树[模板]区间加乘

//Segment Tree
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=500500;
struct Tree
{
    long long int son[2],lazy[2];
    long long int mks[3],bond[2];
    long long int asum;
}tree[M*4];
int num[M];
int n,m,root=0,cnt=1,mod;
void pushup(int cur)
{
    int ls=tree[cur].son[0];
    int rs=tree[cur].son[1];
    tree[cur].bond[0]=tree[ls].bond[0];
    tree[cur].bond[1]=tree[rs].bond[1];
    tree[cur].asum=tree[ls].asum+tree[rs].asum;
}
void built(int L,int R,int cur)
{
    tree[cur].lazy[0]=0;tree[cur].lazy[1]=1;
    if (R==L)
    {
        tree[cur].asum=num[L];
        tree[cur].son[0]=tree[cur].son[1]=-1;
        tree[cur].bond[0]=tree[cur].bond[1]=L;
        return ;
    }
    tree[cur].son[0]=cnt++;
    tree[cur].son[1]=cnt++;
    int mid=(L+R)>>1;
    built(L,mid,tree[cur].son[0]);
    built(mid+1,R,tree[cur].son[1]);
    pushup(cur);
}
void pushdown(int cur)
{
    int lson=tree[cur].son[0], rson=tree[cur].son[1];
    tree[lson].asum=(tree[lson].asum*tree[cur].lazy[1]+tree[cur].lazy[0]*(tree[lson].bond[1]-tree[lson].bond[0]+1))%mod;
    tree[rson].asum=(tree[rson].asum*tree[cur].lazy[1]+tree[cur].lazy[0]*(tree[rson].bond[1]-tree[rson].bond[0]+1))%mod;
    tree[lson].lazy[1]=(tree[lson].lazy[1]*tree[cur].lazy[1])%mod;
    tree[rson].lazy[1]=(tree[rson].lazy[1]*tree[cur].lazy[1])%mod;
    tree[lson].lazy[0]=(tree[lson].lazy[0]*tree[cur].lazy[1]+tree[cur].lazy[0])%mod;
    tree[rson].lazy[0]=(tree[rson].lazy[0]*tree[cur].lazy[1]+tree[cur].lazy[0])%mod;
    tree[cur].lazy[1]=1;tree[cur].lazy[0]=0;
}
void updateadd(int L,int R,int val,int cur)
{
    if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R) 
    {
        tree[cur].asum+=(val*(tree[cur].bond[1]-tree[cur].bond[0]+1));
        tree[cur].asum%=mod;tree[cur].lazy[0]+=val;tree[cur].lazy[0]%=mod;
        return ;
    }
    pushdown(cur);
    int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1;
    if (L<=mid) updateadd(L,R,val,tree[cur].son[0]);
    if (R>mid) updateadd(L,R,val,tree[cur].son[1]);
    pushup(cur);
}
void updatemul(int L,int R,int val,int cur)
{
    if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R)
    {
        tree[cur].asum*=val;tree[cur].asum%=mod;
        tree[cur].lazy[0]*=val;tree[cur].lazy[0]%=mod;
        tree[cur].lazy[1]*=val;tree[cur].lazy[1]%=mod;
        return ;
    }
    pushdown(cur);
    int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1;
    if (L<=mid) updatemul(L,R,val,tree[cur].son[0]);
    if (R>mid) updatemul(L,R,val,tree[cur].son[1]);
    pushup(cur);
}
long long int querysum(int L,int R,int cur)
{
    long long int tot=0;
    if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R) return tree[cur].asum;
    pushdown(cur);
    int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1;
    if (L<=mid) tot+=querysum(L,R,tree[cur].son[0]);
    if (R>mid) tot+=querysum(L,R,tree[cur].son[1]);
    return tot%mod; 
}
int main()
{
    scanf("%d %d %d",&n,&m,&mod);
    for (int i=1;i<=n;i++) scanf("%d",&num[i]),num[i]%=mod;
    built(1,n,root);
    while (m--)
    {
        int a,b,c,d;
        scanf("%d",&d);
        if (d==1)
        {
            scanf("%d %d %d",&a,&b,&c);
            updatemul(a,b,c,root);  
        }
        else if (d==2)
        {
            scanf("%d %d %d",&a,&b,&c);
            updateadd(a,b,c,root);
        }   
        else if (d==3)
        {
            scanf("%d %d",&a,&b);
            cout<<querysum(a,b,root)%mod<<endl;
        }
    }   
    return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80688438