题目
思路
作为线段树模板题,这题主要考查了对lazytag以及先乘后加的使用,
线段树详解
因为是模板,所以这里证明略
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e5+5;
int n,m,p;
int a[maxn];
struct node{int v,mul,add;
}st[maxn*4];
//初始化
void init(int root,int l,int r){st[root].mul=1,st[root].add=0;if(l==r) st[root].v=a[l];else { int mid=l+r>>1;init(root*2,l,mid),init(root*2+1,mid+1,r),st[root].v=st[root*2].v+st[root*2+1].v; }st[root].v%=p;return;
}
void pushdown(int root,int l,int r){int mid=(l+r)/2;st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(mid-l+1))%p,st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-mid))%p,st[root*2].mul=(st[root*2].mul*st[root].mul)%p,st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p,st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p,st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p,st[root].mul=1,st[root].add=0;return;
}
//加
void ud1(int root,int stdl,int stdr,int l,int r,int k){if(r<stdl||stdr<l) return;if(l<=stdl&&stdr<=r) { st[root].v=(st[root].v*k)%p,st[root].mul=(st[root].mul*k)%p,st[root].add=(st[root].add*k)%p;return; }pushdown(root,stdl,stdr);int mid=stdl+stdr>>1;ud1(root*2,stdl,mid,l,r,k),ud1(root*2+1,mid+1,stdr,l,r,k);st[root].v=(st[root*2].v+st[root*2+1].v)%p;return;
}
//乘
void ud2(int root,int stdl,int stdr,int l,int r,int k){if(r<stdl||stdr<l) return;if(l<=stdl&&stdr<=r){st[root].add=(st[root].add+k)%p,st[root].v=(st[root].v+k*(stdr-stdl+1))%p;return;}pushdown(root,stdl,stdr);int mid=stdl+stdr>>1;ud2(root*2,stdl,mid,l,r,k),ud2(root*2+1,mid+1,stdr,l,r,k);st[root].v=(st[root*2].v+st[root*2+1].v)%p;return;
}
//查询区间和
int query(int root,int stdl,int stdr,int l,int r){if(r<stdl||stdr<l) return 0;if(l<=stdl&&stdr<=r) return st[root].v;pushdown(root,stdl,stdr);int mid=(stdl+stdr)/2;return (query(root*2,stdl,mid,l,r)+query(root*2+1,mid+1,stdr,l,r))%p;
}
signed main(){cin>>n>>m>>p;for(int i=1;i<=n;i++) cin>>a[i];init(1,1,n);while(m--){int if_case;cin>>if_case;int x,y,k;switch (if_case){case 1:cin>>x>>y>>k;ud1(1,1,n,x,y,k);break;case 2:cin>>x>>y>>k;ud2(1,1,n,x,y,k);break;case 3:cin>>x>>y;cout<<query(1,1,n,x,y)<<endl;break;}}return 0;
}
end
完结撒花