AHOI2009维护序列--线段树lazy tag模板

来源:互联网 发布:net域名注册 编辑:程序博客网 时间:2024/06/09 14:21
区间加法和乘法,两个lazy数组同时维护。。。。。
#include<iostream>#include<cstdio>using namespace std;typedef long long ll;const int maxn=100005;ll mod;struct Tree{ll sum[maxn<<2],add[maxn<<2],mul[maxn<<2];void Mod(int p){sum[p]%=mod;add[p]%=mod;mul[p]%=mod;}void push_up(int p,int u,int v){sum[p]=(sum[u]+sum[v])%mod;}void push_down(int p,int l,int r,int u,int v,int mid){add[u]=add[u]*mul[p]+add[p];add[v]=add[v]*mul[p]+add[p];mul[u]*=mul[p];mul[v]*=mul[p];sum[u]=sum[u]*mul[p]+add[p]*(mid-l+1);sum[v]=sum[v]*mul[p]+add[p]*(r-mid);add[p]=0,mul[p]=1;Mod(u),Mod(v);}void create_tree(int p,int l,int r){mul[p]=1;if(l==r){scanf("%lld",&sum[p]);sum[p]%=mod;return;}int mid=(l+r)>>1,u=p<<1,v=u+1;create_tree(u,l,mid);create_tree(v,mid+1,r);push_up(p,u,v);}void update(int p,int l,int r,int L,int R,int w,int k){if((l>=L)&&(r<=R)){if(k==1){sum[p]=sum[p]*w;add[p]=add[p]*w;mul[p]=mul[p]*w;}else{sum[p]=sum[p]+(r-l+1)*w;add[p]=add[p]+w;}Mod(p);return;}int mid=(l+r)>>1,u=p<<1,v=u+1;push_down(p,l,r,u,v,mid);if(L<=mid)update(u,l,mid,L,R,w,k);if(R>mid)update(v,mid+1,r,L,R,w,k);push_up(p,u,v);}int query(int p,int l,int r,int L,int R){if((l>=L)&&(r<=R))return sum[p];int mid=(l+r)>>1,u=p<<1,v=u+1,res=0;push_down(p,l,r,u,v,mid);if(L<=mid)res+=query(u,l,mid,L,R);if(R>mid)res+=query(v,mid+1,r,L,R);push_up(p,u,v);return res%mod;}}Tr;int main(){int n,m;scanf("%d%lld",&n,&mod);Tr.create_tree(1,1,n);scanf("%d",&m);while(m--){int k,u,v,w;scanf("%d%d%d",&k,&u,&v);if(k==3)printf("%d\n",Tr.query(1,1,n,u,v));else{scanf("%d",&w);Tr.update(1,1,n,u,v,w,k);}}return 0;}

2 0
原创粉丝点击