普通的线段树,WA#2#9#10
码风奇怪勿喷 ( 抱头
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000010;
int n,m,p;
ll arr[N];
ll tree[N<<2];
ll lazyp[N<<2];//
ll lazym[N<<2];//双lazytag
ll pointer;
/*lazytag*/
inline void func(int node,int l,int r,int add,int mul)
{
tree[node]=(tree[node]*mul+(r-l+1)*add)%p;
lazym[node]=lazym[node]*mul%p;
lazyp[node]=(lazyp[node]*mul+add)%p;
}
inline void push_down(int node,int l,int r)
{
//先更新乘法tag再更新加法tag
ll mid=l+r>>1;
int lnode=node<<1;
int rnode=node<<1|1;
func(lnode,l,mid,lazyp[node],lazym[node]);
func(rnode,mid+1,r,lazyp[node],lazym[node]);
lazym[node]=1;
lazyp[node]=0;
}
/*pushup*/
void push_up(int node)
{
tree[node]=(tree[node<<1]%p+tree[node<<1|1]%p)%p;
}
void build(int node,int start,int end)
{
lazym[node]=1;
lazyp[node]=0;
if(start==end)
{
tree[node]=arr[start];
return ;
}
int mid=start+end>>1;
int lnode=node<<1;
int rnode=node<<1|1;
build(lnode,start,mid);
build(rnode,mid+1,end);
push_up(node);
}
void update(int node,int start,int end,int l,int r,int add,int mul)
{
if(l<=start&&end<=r)
{
func(node,start,end,add,mul);
return ;
}
push_down(node,start,end);
int mid=start+end>>1;
int lnode=node<<1;
int rnode=node<<1|1;
if(l<=mid) update(lnode,start,mid,l,r,add,mul);
if(r>mid) update(rnode,mid+1,end,l,r,add,mul);
push_up(node);
}
ll query(int node,int start,int end,int l,int r)
{
if(end<l||start>r) return 0;
if(l<=start&&end<=r) return tree[node]%p;
pointer=node;
push_down(node,start,end);
int mid=start+end>>1;
int lnode=node<<1;
int rnode=node<<1|1;
ll suml=query(lnode,start,mid,l,r)%p;
ll sumr=query(rnode,mid+1,end,l,r)%p;
return (suml%p+sumr%p)%p;
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=n;i++)
{
scanf("%lld",arr+i);
}
build(1,1,n);
for(int i=1;i<=m;i++)
{
int k;
scanf("%d",&k);
if(k==1)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
update(1,1,n,x,y,0,z);
}
if(k==2)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
update(1,1,n,x,y,z,1);
}
if(k==3)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",query(1,1,n,x,y)%p);
}
}
return 0;
}