```cpp
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define mod 998244353
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<int, int>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
using namespace std;
#define ll long long
#define N 100010
#define int long long
/*----------------以上是缺省源,(基本没用)---------*/
int n,q,m;//如题
int a[N];//记录原数列
ll tree[4*N];//用于存储树
int lazy[4*N],lazye[N*4];//lazye是乘法的标记,lazy是加法的
/*函数声明*/
int read();
void update(int s,int t,int p);
ll getsum(int l,int r,int s,int t,int p);
void build(int l,int r,int p);
void pplus(int l,int r,int k,int s,int t,int p);
void update(int s,int t,int p);
/**/
void build(int l,int r,int p){//建树 l指的是左端点,r右端点,p为节点编号
lazye[p]=1;
lazy[p]=0;
if(l==r){
tree[p]=a[l];
return ;
}
int mid=l+((r-l)>>1);
build(l,mid,p*2);
build(mid+1,r,p*2+1);
tree[p]=(tree[p*2]+tree[p*2+1])%m;
}
ll getsum(int l,int r,int s,int t,int p){//求和
//l指的是要求和的左端点,r右端点,p为节点编号
//s指的是当前节点的左端点,t右端点
ll sum=0ll;
if(l<=s&&r>=t){
return tree[p];
}
int mid=s+((t-s)>>1);
if(lazy[p]!=0||lazye[p]!=1){
update(s,t,p);
}
if(l<=mid){
sum=(sum+getsum(l,r,s,mid,p*2))%m;
}
if(r>mid){
sum=(sum+getsum(l,r,mid+1,t,p*2+1))%m;
}
return sum%m;
}
void update(int s,int t,int p){//向下传递懒惰标记
//s指的是当前节点的左端点,t右端点 p为节点编号
int mid=s+((t-s)>>1);
if(lazye[p]!=1){
lazye[p*2] =(lazye[p*2] *lazye[p])%m;
lazye[p*2+1]=(lazye[p*2+1]*lazye[p])%m;
tree[p*2] =(tree[p*2] *lazye[p])%m;
tree[p*2+1] =(tree[p*2+1] *lazye[p])%m;
lazy[p*2] =(lazy[p*2] *lazye[p])%m;
lazy[p*2+1] =(lazy[p*2+1] *lazye[p])%m;
lazye[p]=1;
}
if(lazy[p]!=0){
tree[p*2]=(tree[p*2]+(lazy[p]*(mid-s+1)))%m;
tree[p*2+1]=(tree[p*2+1]+(lazy[p]*(t-mid)))%m;
lazy[p*2]=(lazy[p*2]+lazy[p])%m;
lazy[p*2+1]=(lazy[p*2+1]+lazy[p])%m;
lazy[p]=0;
}
}
void explus(int l,int r,int k,int s,int t,int p){//乘法
//l指的是要求和的左端点,r右端点,p为节点编号
//s指的是当前节点的左端点,t右端点 k是要乘的数
if(l<=s&&r>=t){
tree[p]=(tree[p]*k)%m;
lazye[p]=(lazye[p]*k)%m;
lazy[p]=(lazy[p]*k)%m;
return ;
}
// if(lazye[p]!=1&&s!=t){
update(s,t,p);
// }
int mid=s+((t-s)>>1);
if(l<=mid){
explus(l,r,k,s,mid,p*2);
}
if(r>=mid+1){
explus(l,r,k,mid+1,t,p*2+1);
}
tree[p]=(tree[p*2]+tree[p*2+1])%m;
}
void pplus(int l,int r,int k,int s,int t,int p){//加法
//l指的是要求和的左端点,r右端点,p为节点编号
//s指的是当前节点的左端点,t右端点 k是要加的数
if(l<=s&&r>=t){
tree[p]=(tree[p]+((t-s+1)*k))%m;
lazy[p]=(lazy[p]+k)%m;
return ;
}
// if(lazy[p]!=0&&s!=t){
update(s,t,p);
// }
int mid=s+((t-s)>>1);
if(l<=mid){
pplus(l,r,k,s,mid,p*2);
}
if(r>mid){
pplus(l,r,k,mid+1,t,p*2+1);
}
tree[p]=(tree[p*2]+tree[p*2+1])%m;
}
signed main()
{
//freopen("bigdate.in","r",stdin);
// freopen("PPP","w",stdout);
ios::sync_with_stdio(false);
cin>>n>>q>>m;
for(int i=1;i<=n;i++)cin>>a[i];
build(1,n,1);
while(q--){
int op;
cin>>op;
if(op==1){
int x,y,k;
cin>>x>>y>>k;
explus(x,y,k,1,n,1);
}
else if(op==2){
int x,y,k;
cin>>x>>y>>k;
pplus(x,y,k,1,n,1);
}
else{
int x,y;
cin>>x>>y;
cout<<getsum(x,y,1,n,1)<<endl;
}
}
return 0;
}
//效率是代码的事,优雅是一辈子的事w~
//样例过了,自己造的几个小数据也过了,下载了第二个点,fc了一下也是过的,但是交上去就是不对:(
```
调好了,pushdown的问题,把乘的懒标记更新完后,不要在加的懒标记里又更新一遍。
by LIUYC_C @ 2023-11-07 21:04:41
@[LIUYC_C](/user/819273) 然后你的快读似乎也有问题。
by LIUYC_C @ 2023-11-07 21:06:21
@[LIUYC_C](/user/819273) 谢谢谢谢大佬orz \
真抱歉现在才看见\
谢谢!
by Happy_King @ 2023-11-08 15:22:21