洛谷传送门
BZOJ传送门
解析:
由于乘法的优先级大于加法,我们考虑以乘法为主维护(就是尽量不去动乘法的延迟标记)。
维护方式如下:
1.遇到加法,直接加在加法标记上,并更新当前数列的和。
2.遇到乘法,同时更新乘法标记,加法标记,当前序列和。
3.下传标记时,先传乘法,再传加法。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline void outint(ll a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
cs int N=100005;
ll mod;
int n;
int mul[N<<2],add[N<<2],sum[N<<2],siz[N<<2];
inline void pushup(int k){
sum[k]=(1ll*sum[k<<1]+sum[k<<1|1])%mod;
}
inline void build(int k,int l,int r){
add[k]=0;
mul[k]=1;
siz[k]=r-l+1;
if(l==r){
sum[k]=getint()%mod;
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
inline void pushadd(int k,int val){
add[k]=(1ll*add[k]+val)%mod;
sum[k]=(sum[k]+1ll*val*siz[k]%mod)%mod;
}
inline void pushmul(int k,int val){
mul[k]=(1ll*mul[k]*val)%mod;
add[k]=(1ll*add[k]*val)%mod;
sum[k]=(1ll*sum[k]*val)%mod;
}
inline void pushdown(int k){
if(mul[k]!=1){
pushmul(k<<1,mul[k]);
pushmul(k<<1|1,mul[k]);
mul[k]=1;
}
if(add[k]){
pushadd(k<<1,add[k]);
pushadd(k<<1|1,add[k]);
add[k]=0;
}
}
inline void modifymul(int k,int l,int r,cs int &ql,cs int &qr,cs int &val){
if(ql<=l&&r<=qr){
pushmul(k,val);
return;
}
pushdown(k);
int mid=(l+r)>>1;
if(ql<=mid)modifymul(k<<1,l,mid,ql,qr,val);
if(mid<qr)modifymul(k<<1|1,mid+1,r,ql,qr,val);
pushup(k);
}
inline void modifyadd(int k,int l,int r,cs int &ql,cs int &qr,cs int &val){
if(ql<=l&&r<=qr){
pushadd(k,val);
return ;
}
pushdown(k);
int mid=(l+r)>>1;
if(ql<=mid)modifyadd(k<<1,l,mid,ql,qr,val);
if(mid<qr)modifyadd(k<<1|1,mid+1,r,ql,qr,val);
pushup(k);
}
inline int query(int k,int l,int r,cs int &ql,cs int &qr){
if(ql<=l&&r<=qr)return sum[k];
pushdown(k);
int mid=(l+r)>>1;
if(mid<ql)return query(k<<1|1,mid+1,r,ql,qr);
if(qr<=mid)return query(k<<1,l,mid,ql,qr);
return (query(k<<1,l,mid,ql,qr)+query(k<<1|1,mid+1,r,ql,qr))%mod;
}
signed main(){
n=getint();
mod=getint();
build(1,1,n);
int m=getint();
while(m--){
int op=getint();
int l=getint(),r=getint();
switch(op){
case 1:{
int val=getint()%mod;
modifymul(1,1,n,l,r,val);
break;
}
case 2:{
int val=getint()%mod;
modifyadd(1,1,n,l,r,val);
break;
}
case 3:{
outint(query(1,1,n,l,r));pc('\n');
break;
}
}
}
return 0;
}