洛谷 3373 线段树 2
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #define nn 100011 using namespace std; typedef long long lo; lo v[nn<<2],mu[nn<<2],ad[nn<<2],a[nn],mod; lo read() { lo ans=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();} return ans*f; } lo qmod(lo x) { return x>=mod? x-mod:x; } void build(int k,int l,int r) { mu[k]=1; //乘标记赋为1 if(l==r) { v[k]=a[l];return; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); v[k]=qmod(v[k<<1]+v[k<<1|1]); } void pushdown(int k,int l,int r) { int mid=(l+r)>>1; v[k<<1]=qmod(v[k<<1]*mu[k]%mod+ad[k]*(mid-l+1)%mod); v[k<<1|1]=qmod(v[k<<1|1]*mu[k]%mod+ad[k]*(r-mid)%mod); mu[k<<1]=mu[k<<1]*mu[k]%mod; mu[k<<1|1]=mu[k<<1|1]*mu[k]%mod; ad[k<<1]=qmod(ad[k<<1]*mu[k]%mod+ad[k]); ad[k<<1|1]=qmod(ad[k<<1|1]*mu[k]%mod+ad[k]); mu[k]=1;ad[k]=0; //mu[k]=1 } void amend_mul(int k,int l,int r,int ml,int mr,lo x) { if(mr<l||ml>r) return; if(ml<=l&&mr>=r) { mu[k]=mu[k]*x%mod; ad[k]=ad[k]*x%mod; v[k]=v[k]*x%mod; return; } if(mu[k]!=1||ad[k]) pushdown(k,l,r); int mid=(l+r)>>1; amend_mul(k<<1,l,mid,ml,mr,x); amend_mul(k<<1|1,mid+1,r,ml,mr,x); v[k]=qmod(v[k<<1]+v[k<<1|1]); } void amend_add(int k,int l,int r,int ml,int mr,lo x) { if(mr<l||ml>r) return; if(ml<=l&&mr>=r) { ad[k]=qmod(ad[k]+x); // v[k]=qmod(v[k]+x*(r-l+1)%mod); //区间加 return; } if(mu[k]!=1||ad[k]) pushdown(k,l,r); int mid=(l+r)>>1; amend_add(k<<1,l,mid,ml,mr,x); amend_add(k<<1|1,mid+1,r,ml,mr,x); v[k]=qmod(v[k<<1]+v[k<<1|1]); } lo query(int k,int l,int r,int ql,int qr) { if(qr<l||ql>r) return 0; if(ql<=l&&qr>=r) return v[k]; if(mu[k]!=1||ad[k]) pushdown(k,l,r); int mid=(l+r)>>1; return qmod(query(k<<1,l,mid,ql,qr)+query(k<<1|1,mid+1,r,ql,qr)); } int main() { int n,m,x,y,k,opt; n=read();m=read();mod=read(); for(int i=1;i<=n;i++) a[i]=read()%mod; build(1,1,n); for(int i=1;i<=m;i++) { opt=read();x=read();y=read(); if(opt==1) { k=read(); amend_mul(1,1,n,x,y,k%mod); } else if(opt==2) { k=read(); amend_add(1,1,n,x,y,k%mod); } else printf("%lld\n",query(1,1,n,x,y)); } return 0; }