【BZOJ 1798】[Ahoi2009]Seq 维护序列seq

乘法和加法可以都保留 加个小处理!

#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN 100000
#define LL long long
LL a[MAXN*4],c[MAXN*4],j[MAXN*4],num[MAXN*4];
LL n,p,m;
void Build(int now,int L,int R)
{
    c[now]=1;
    if(L==R) {a[now]=num[L];return;}
    int mid=(L+R)/2;
    Build(now*2,L,mid);
    Build(now*2+1,mid+1,R);
    a[now]=a[now*2]+a[now*2+1];
}
void Pushdown(int now,int L,int R)
{
    int mid=(L+R)/2;
    if(L!=R) 
    {
        c[now*2]*=c[now];                       a[now*2]*=c[now];
        c[now*2+1]*=c[now];                     a[now*2+1]*=c[now];
        j[now*2]=j[now*2]*c[now]+j[now];        a[now*2]+=(mid-L+1)*j[now];
        j[now*2+1]=j[now*2+1]*c[now]+j[now];    a[now*2+1]+=(R-mid)*j[now];
        c[now*2]%=p;
        c[now*2+1]%=p;
        j[now*2]%=p;
        j[now*2+1]%=p;
        a[now*2]%=p;
        a[now*2+1]%=p;
    }
    c[now]=1;j[now]=0;
}
void Change(int now,int L,int R,int s,int t,int cc,int jj)
{
    
    if(s<=L&&R<=t) {c[now]*=cc;c[now]%=p;j[now]=(j[now]*cc+jj)%p;a[now]*=cc;a[now]+=(R-L+1)*jj;a[now]%=p;return;}
    Pushdown(now,L,R);
    int mid=(L+R)/2;
    if(t<=mid) Change(now*2,L,mid,s,t,cc,jj);
    else if(s>=mid+1) Change(now*2+1,mid+1,R,s,t,cc,jj);
    else Change(now*2,L,mid,s,t,cc,jj),Change(now*2+1,mid+1,R,s,t,cc,jj);
    a[now]=(a[now*2]+a[now*2+1])%p;
}
int Query(int now,int L,int R,int s,int t)
{
    if(s<=L&&R<=t) return a[now];
    Pushdown(now,L,R);
    int mid=(L+R)/2;
    if(t<=mid) return Query(now*2,L,mid,s,t)%p;
    else if(s>=mid+1) return Query(now*2+1,mid+1,R,s,t)%p;
    else return (Query(now*2,L,mid,s,t)+Query(now*2+1,mid+1,R,s,t))%p;
}
inline int Read()
{
    int ans=0;
    char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while('0'<=c&&c<='9')ans=ans*10+c-'0',c=getchar();
    return ans;
}
int main()
{
    scanf("%lld %lld",&n,&p);
    for(int i=1;i<=n;i++) num[i]=Read();
    Build(1,1,n);
    scanf("%lld",&m);
    for(int opt,x,y,z,i=1;i<=m;i++)
    {
        opt=Read();
        switch(opt)
        {
            case 1:x=Read(),y=Read(),z=Read();Change(1,1,n,x,y,z,0);break;
            case 2:x=Read(),y=Read(),z=Read();Change(1,1,n,x,y,1,z);break;
            case 3:x=Read();y=Read();printf("%d\n",Query(1,1,n,x,y));break;
        }
    }
    return 0;
}

你可能感兴趣的:(【BZOJ 1798】[Ahoi2009]Seq 维护序列seq)