震惊,双倍经验,依旧是线段树的乘法修改
#include<bits/stdc++.h> using namespace std; const int maxn=1000010; struct sege_tree { int l; int r; long long lazymul; long long lazyadd; long long v; }tree[7*maxn]; int a[maxn]; long long p,ans; int n,m,opt,l,r; long long t; void build(int now,int l,int r) { tree[now].l=l; tree[now].r=r; tree[now].lazymul=1; tree[now].lazyadd=0; if(l==r) { tree[now].v=a[l]; return; } else { int mid=(l+r)>>1; build(now*2,l,mid); build(now*2+1,mid+1,r); tree[now].v=tree[now*2].v+tree[now*2+1].v; } tree[now].v%=p; return; } void pushdown(int now,int l,int r)//标记下传 { int mid=(l+r)>>1; tree[now*2].v=(tree[now*2].v*tree[now].lazymul+tree[now].lazyadd*(mid-l+1))%p; tree[now*2+1].v=(tree[now*2+1].v*tree[now].lazymul+tree[now].lazyadd*(r-mid))%p; tree[now*2].lazymul=(tree[now*2].lazymul*tree[now].lazymul)%p; tree[now*2+1].lazymul=(tree[now*2+1].lazymul*tree[now].lazymul)%p; tree[now*2].lazyadd=(tree[now*2].lazyadd*tree[now].lazymul+tree[now].lazyadd)%p; tree[now*2+1].lazyadd=(tree[now*2+1].lazyadd*tree[now].lazymul+tree[now].lazyadd)%p; tree[now].lazymul=1; tree[now].lazyadd=0; return; } void update1(int now,int stdl,int stdr,int l,int r,long long k) { if(l>stdr||r<stdl) { return; } if(l<=stdl&&r>=stdr) { tree[now].v=(tree[now].v*k)%p; tree[now].lazymul=(tree[now].lazymul*k)%p; tree[now].lazyadd=(tree[now].lazyadd*k)%p; return; } pushdown(now,stdl,stdr); int mid=(stdl+stdr)>>1; update1(now*2,stdl,mid,l,r,k); update1(now*2+1,mid+1,stdr,l,r,k); tree[now].v=(tree[now*2].v+tree[now*2+1].v)%p; return; } void update2(int now,int stdl,int stdr,int l,int r,long long k) { if(l>stdr||r<stdl) { return; } if(l<=stdl&&r>=stdr) { tree[now].lazyadd=(tree[now].lazyadd+k)%p; tree[now].v=(tree[now].v+k*(stdr-stdl+1))%p; return; } pushdown(now,stdl,stdr); int mid=(stdl+stdr)>>1; update2(now*2,stdl,mid,l,r,k); update2(now*2+1,mid+1,stdr,l,r,k); tree[now].v=(tree[now*2].v+tree[now*2+1].v)%p; } long long query(int now,int stdl,int stdr,int l,int r) { if(stdl>r||stdr<l) { return 0; } if(stdl>=l&&stdr<=r) { return tree[now].v; } pushdown(now,stdl,stdr); int mid=(stdl+stdr)>>1; return (query(now*2,stdl,mid,l,r)+query(now*2+1,mid+1,stdr,l,r))%p; } int main() { cin>>n>>p; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } build(1,1,n); cin>>m; while(m--) { scanf("%d",&opt); if(opt==1) { cin>>l>>r>>t; update1(1,1,n,l,r,t); } else if(opt==2) { cin>>l>>r>>t; update2(1,1,n,l,r,t); } else { cin>>l>>r; cout<<query(1,1,n,l,r)<<endl; } } return 0; }