analysis
关键是优先级
我是真的看不懂题解里面那个自定义优先级是个什么鬼
按照我的理解,优先级只能先乘后加
如:
∑
i
=
1
n
(
a
[
i
]
+
k
)
=
∑
i
=
1
n
a
[
i
]
+
k
×
n
\sum_{i=1}^{n}(a[i]+k)=\sum_{i=1}^{n}a[i]+k\times n
∑i=1n(a[i]+k)=∑i=1na[i]+k×n
意思就是一个区间同时乘上一个数的时候,相当于把其原数列乘上一个数同时把懒标记乘上一个数然后加起来
所以在pushdown的时候,若涉及乘法标记应该将子区间的add标记乘上一个值然后再下传标记
这样的话就保证了优先级
(感觉自己的思路其实还是挺混乱)
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define ll long long
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
const int maxn=100000+10;
const int maxm=100000+10;
int n,m;
ll mod;
ll sum[maxn<<2];
ll lazyA[maxn<<2];
ll lazyM[maxn<<2];//long long
inline void pushup(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
sum[rt]%=mod;
}
void buildtree(int l,int r,int rt){
lazyA[rt]=0;
lazyM[rt]=1;
if(l==r){
read(sum[rt]);
sum[rt]%=mod;
return;
}
int mid=(l+r)>>1;
buildtree(l,mid,rt<<1);
buildtree(mid+1,r,rt<<1|1);
pushup(rt);
}
inline void pushdown(int rt,int l,int r){
if(!lazyA[rt]&&lazyM[rt]==1)return;
int mid=(l+r)>>1;
sum[rt<<1]=(lazyM[rt]*sum[rt<<1])%mod;
sum[rt<<1|1]=(sum[rt<<1|1]*lazyM[rt])%mod;//写反了??
sum[rt<<1]=((mid-l+1)*lazyA[rt]+sum[rt<<1])%mod;
sum[rt<<1|1]=((r-(mid+1)+1)*lazyA[rt]+sum[rt<<1|1])%mod;
lazyA[rt<<1|1]=(lazyA[rt]+lazyA[rt<<1|1]*lazyM[rt])%mod;
lazyA[rt<<1]=(lazyA[rt]+lazyA[rt<<1]*lazyM[rt])%mod;
lazyM[rt<<1]=(lazyM[rt]*lazyM[rt<<1])%mod;
lazyM[rt<<1|1]=(lazyM[rt]*lazyM[rt<<1|1])%mod;
lazyA[rt]=0;
lazyM[rt]=1;
}
void Add(int l,int r,int nl,int nr,int rt,ll w){
if(l<=nl&&nr<=r){
sum[rt]=(w*(nr-nl+1)+sum[rt])%mod;
lazyA[rt]=(w+lazyA[rt])%mod;
return;
}
pushdown(rt,nl,nr);
int mid=(nl+nr)>>1;
if(mid>=l)Add(l,r,nl,mid,rt<<1,w);
if(mid<r)Add(l,r,mid+1,nr,rt<<1|1,w);
pushup(rt);
}
void Mul(int l,int r,int nl,int nr,int rt,ll w){
if(l<=nl&&nr<=r){
sum[rt]=(w*sum[rt])%mod;
lazyA[rt]=(lazyA[rt]*w)%mod;
lazyM[rt]=w*lazyM[rt]%mod;
return;
}
pushdown(rt,nl,nr);
int mid=(nl+nr)>>1;
if(mid>=l)Mul(l,r,nl,mid,rt<<1,w);
if(mid<r)Mul(l,r,mid+1,nr,rt<<1|1,w);
pushup(rt);
}
ll Que(int l,int r,int nl,int nr,int rt){
if(l<=nl&&nr<=r){
return sum[rt];
}
pushdown(rt,nl,nr);
int mid=(nl+nr)>>1;
ll res=0;
if(mid>=l)
res+=Que(l,r,nl,mid,rt<<1);
if(mid<r)
res+=Que(l,r,mid+1,nr,rt<<1|1);
pushup(rt);
return res;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
read(n),read(mod);
buildtree(1,n,1);
read(m);
int op;
loop(i,1,m){
read(op);
if(op==1){
int x,y;
ll k;
read(x),read(y),read(k);
Mul(x,y,1,n,1,k);
}
else if(op==2){
int x,y;
ll k;
read(x),read(y),read(k);
Add(x,y,1,n,1,k);
}
else if(op==3){
int x,y;
read(x),read(y);
printf("%lld\n",(Que(x,y,1,n,1))%mod);
}
}
return 0;
}