题目大意:给定一个有图片说明 个元素序列,有四种操作和一种询问.

  • 1 L R K 让区间图片说明 的元素加上图片说明 .
  • 2 L R K 让区间图片说明 的元素乘上图片说明 .
  • 3 L R K 让区间图片说明 的元素变为图片说明 .
  • 4 L R K 在末尾位置添加一个元素值为图片说明 .
  • 5 L R 询问区间图片说明 元素的值的和.

分析: 赛中分析,前四个操作都是线段树的操作,后面看到操作四,以为不能写线段树,直接码分块,后面T了三十发直接自闭.

赛后分析:显然我们可以直接建n+m大小的线段树,然后直接操作.(惊了
推标记直接用两个mul 和add 维护乘法和加法,这种操作就是码板子.

#include<bits/stdc++.h>
#define ls cur<<1
#define rs cur<<1|1

using namespace std;

const int maxn=2e5+10;

typedef long long ll;
ll  mod; 


struct node1{
    int l;
    int r;
    ll sum1,mul,lazy;
}t[maxn<<2];

ll a[maxn];

void pushup( int cur ) //ok
{
    t[cur].sum1=( t[ls].sum1+t[rs].sum1 )%mod;
}


void cal( int cur,ll x,ll y )
{
    ll len=1ll*( t[cur].r-t[cur].l+1 );
    t[cur].sum1=( x*t[cur].sum1%mod+(y*len)%mod )%mod;
    t[cur].mul=(t[cur].mul*x)%mod;
    t[cur].lazy=( t[cur].lazy*x%mod+y )%mod;
}

void pushdown( int cur ) //ok
{
    if( t[cur].mul!=1ll || t[cur].lazy )
    {
        cal( ls,t[cur].mul,t[cur].lazy );
        cal( rs,t[cur].mul,t[cur].lazy );
        t[cur].mul=1ll;
        t[cur].lazy=0;
    }
}



void build( int cur ,int l,int r )
{
    t[cur].l=l;t[cur].r=r;
    t[cur].mul=1ll;
    t[cur].lazy=t[cur].sum1=0ll;
    if( l == r )
    {
        t[cur].sum1=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup( cur );
}

void update( int cur,int L,int R ,ll x,ll y )
{
    int l=t[cur].l,r=t[cur].r;
    if( L<=l && r<=R )
    {
        cal(cur,x,y);
        return;
    }
    pushdown( cur );
    int mid=(l+r)>>1;
    if( L<=mid ) update(ls,L,R,x,y);
    if( R>mid ) update(rs,L,R,x,y);
    pushup( cur );
}


ll get_Sum( int cur,int L,int R )
{
    int l=t[cur].l,r=t[cur].r;
    if( L<=l && r<=R )    return t[cur].sum1;
    ll ans=0;
    pushdown( cur );
    int mid=(l+r)>>1;
    if( L<=mid ) ans+=get_Sum(ls,L,R);
    ans%=mod;
    if( R>mid ) ans+=get_Sum(rs,L,R);
    ans%=mod;
    return ans;
}

int main()
{
    int n,m;
    scanf("%d%d%lld",&n,&m,&mod);
    for( int i=1;i<=n;i++ ) scanf("%lld",&a[i]);
    build(1,1,n+m);
    int now=n;
    while( m-- )
    {
        int op,l,r,c;
        scanf("%d",&op);
        if( op <=3 )
        {
            scanf("%d%d%d",&l,&r,&c);
            if( op==1 ) update(1,l,r,1,c);
            if( op==2 ) update(1,l,r,c,0);
            if( op==3 ) update(1,l,r,0,c);
        }
        else if( op==4 )
        {
            scanf("%d",&c);
            now++;
            update(1,now,now,0,c);
        }
        else
        {
            scanf("%d%d",&l,&r);
            printf("%lld\n",get_Sum(1,l,r));
        }
    }
}