这个代码一开始是30pts,改了改变成0pts了,于是下载了第二个数据,本地测发现是对的,然后交是0pts,样例和自己整的几个小数据也都对,完全不明白是哪里错了………… 谢谢大佬们指点!
#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);
/**/
inline int read()/*快读,与题目无关*/
{
int res=0,ch,flag=0;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return flag?-res:res;
}
void build(int l,int r,int p){//建树 l指的是左端点,r右端点,p为节点编号
lazye[p]=1;
lazy[p]=0;
if(l==r){
tree[p]=read();
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;
return ;
}
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]*lazye[p])+(lazy[p]*(mid-s+1)))%m;
tree[p*2+1]=((tree[p*2+1]*lazye[p])+(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("P3373_2.in","r",stdin);
// freopen("PPP","w",stdout);
n=read();
q=read();
m=read();
build(1,n,1);
while(q--){
int op;
op=read();
if(op==1){
int x,y,k;
x=read();
y=read();
k=read();
explus(x,y,k,1,n,1);
}
else if(op==2){
int x,y,k;
x=read();
y=read();
k=read();
pplus(x,y,k,1,n,1);
}
else{
int x,y;
x=read();
y=read();
int ans=getsum(x,y,1,n,1);
cout<<ans<<endl;
}
}
return 0;
}
//效率是代码的事,优雅是一辈子的事w~
//样例过了,自己造的几个小数据也过了,下载了第二个点,fc了一下也是过的,但是交上去就是不对:(