1. 程式人生 > >2018.10.08【AHOI2009】【洛谷P2023】【BZOJ1798】維護序列(線段樹)

2018.10.08【AHOI2009】【洛谷P2023】【BZOJ1798】維護序列(線段樹)

洛谷傳送門

解析:

由於乘法的優先順序大於加法,我們考慮以乘法為主維護(就是儘量不去動乘法的延遲標記)。

維護方式如下: 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; }