求助!萌新写的线段树,悬一关

P3373 【模板】线段树 2

```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


|