2018.10.08【AHOI2009】【洛谷P2023】【BZOJ1798】維護序列(線段樹)
阿新 • • 發佈:2018-12-14
洛谷傳送門
解析:
由於乘法的優先順序大於加法,我們考慮以乘法為主維護(就是儘量不去動乘法的延遲標記)。
維護方式如下: 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;
}