我偏要先下传加。。。
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100500 using namespace std; long long ls[maxn<<2],rs[maxn<<2],val[maxn<<2],lazy1[maxn<<2],lazy2[maxn<<2]; long long n,p,m,a,b,c,d,w[maxn],tot=0,root; void pushup(long long now) { val[now]=(val[ls[now]]+val[rs[now]])%p; } void build(long long &now,long long left,long long right) { now=++tot;lazy1[now]=0;lazy2[now]=1; if (left==right) { val[now]=w[left]%p; return; } long long mid=(left+right)>>1; build(ls[now],left,mid); build(rs[now],mid+1,right); pushup(now); } void pushdown(long long now,long long left,long long right) { long long mid=(left+right)>>1; lazy1[ls[now]]=(lazy1[ls[now]]*lazy2[now]+lazy1[now])%p; lazy1[rs[now]]=(lazy1[rs[now]]*lazy2[now]+lazy1[now])%p; lazy2[ls[now]]=(lazy2[ls[now]]*lazy2[now])%p; lazy2[rs[now]]=(lazy2[rs[now]]*lazy2[now])%p; val[ls[now]]=(val[ls[now]]*lazy2[now]+lazy1[now]*(mid-left+1))%p; val[rs[now]]=(val[rs[now]]*lazy2[now]+lazy1[now]*(right-mid))%p; lazy1[now]=0;lazy2[now]=1; } void modify(long long now,long long left,long long right,long long l,long long r,long long type,long long x) { pushdown(now,left,right); if ((left==l) && (right==r)) { if (type==1) {lazy1[now]+=x;lazy1[now]%=p;val[now]+=x*(right-left+1);val[now]%=p;} else {lazy2[now]*=x;lazy2[now]%=p;lazy1[now]*=x;lazy1[now]%=p;val[now]*=x;val[now]%=p;} return; } long long mid=(left+right)>>1; if (r<=mid) modify(ls[now],left,mid,l,r,type,x); else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,type,x); else { modify(ls[now],left,mid,l,mid,type,x); modify(rs[now],mid+1,right,mid+1,r,type,x); } pushup(now); } long long ask(long long now,long long left,long long right,long long l,long long r) { pushdown(now,left,right); if ((left==l) && (right==r)) return val[now]%p; long long mid=(left+right)>>1; if (r<=mid) return ask(ls[now],left,mid,l,r)%p; else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r)%p; else return (ask(ls[now],left,mid,l,mid)+ask(rs[now],mid+1,right,mid+1,r))%p; } void work1() { scanf("%lld%lld%lld",&b,&c,&d); modify(root,1,n,b,c,2,d); } void work2() { scanf("%lld%lld%lld",&b,&c,&d); modify(root,1,n,b,c,1,d); } void work3() { scanf("%lld%lld",&b,&c); printf("%lld\n",ask(root,1,n,b,c)%p); } int main() { scanf("%lld%lld",&n,&p); for (long long i=1;i<=n;i++) scanf("%lld",&w[i]); build(root,1,n); scanf("%lld",&m); for (long long i=1;i<=m;i++) { scanf("%lld",&a); if (a==1) work1(); else if (a==2) work2(); else work3(); } return 0; }