【模板】多標記線段樹
阿新 • • 發佈:2018-11-19
維護一個長度為 N 的序列,支援區間加和、區間乘積、查詢區間和操作。
程式碼如下
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+10; inline int read(){ int x=0,f=1;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch)); do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch)); return f*x; } int n,q,mod,a[maxn]; struct node{int lc,rc;long long atag,mtag,sum;}; struct Segment_Tree{ #define ls t[k].lc #define rs t[k].rc node t[maxn<<1];int tot; Segment_Tree():tot(1){memset(t,0,sizeof(t));} inline void pushup(int k){t[k].sum=t[ls].sum+t[rs].sum;} inline void pushdown(int k,int l,int r){ int mid=l+r>>1; t[ls].sum=(t[ls].sum*t[k].mtag+(mid-l+1)*t[k].atag)%mod; t[ls].atag=(t[ls].atag*t[k].mtag+t[k].atag)%mod,t[ls].mtag=t[ls].mtag*t[k].mtag%mod; t[rs].sum=(t[rs].sum*t[k].mtag+(r-mid)*t[k].atag)%mod; t[rs].atag=(t[rs].atag*t[k].mtag+t[k].atag)%mod,t[rs].mtag=t[rs].mtag*t[k].mtag%mod; t[k].atag=0,t[k].mtag=1; } void build(int k,int l,int r){ if(l==r){t[k].sum=a[l],t[k].mtag=1;return;} int mid=l+r>>1; ls=++tot,build(ls,l,mid); rs=++tot,build(rs,mid+1,r); pushup(k);t[k].atag=0,t[k].mtag=1; } void modify(int k,int l,int r,int x,int y,int val,int opt){ if(l==x&&r==y){ if(opt==1)t[k].atag=t[k].atag*val%mod,t[k].mtag=t[k].mtag*val%mod,t[k].sum=t[k].sum*val%mod; else t[k].atag=(t[k].atag+val)%mod,t[k].sum=(t[k].sum+(r-l+1)*(long long)val)%mod; return; } int mid=l+r>>1; pushdown(k,l,r); if(y<=mid)modify(ls,l,mid,x,y,val,opt); else if(x>mid)modify(rs,mid+1,r,x,y,val,opt); else modify(ls,l,mid,x,mid,val,opt),modify(rs,mid+1,r,mid+1,y,val,opt); pushup(k); } long long query(int k,int l,int r,int x,int y){ if(l==x&&r==y)return t[k].sum%mod; int mid=l+r>>1; pushdown(k,l,r); if(y<=mid)return query(ls,l,mid,x,y)%mod; else if(x>mid)return query(rs,mid+1,r,x,y)%mod; else return (query(ls,l,mid,x,mid)+query(rs,mid+1,r,mid+1,y))%mod; } }sgt; void read_and_parse(){ n=read(),q=read(),mod=read(); for(int i=1;i<=n;i++)a[i]=read(); sgt.build(1,1,n); } void solve(){ int opt,l,r,val; while(q--){ opt=read(),l=read(),r=read(); if(opt==1||opt==2)val=read(),sgt.modify(1,1,n,l,r,val,opt); else printf("%lld\n",sgt.query(1,1,n,l,r)); } } int main(){ read_and_parse(); solve(); return 0; }