P3373 【模板】线段树 2
这道题WA了好多次,down函数不会写
核心: mui[root]改动时,add[root]也要改动
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+7;
int n,m,p;
long long a[MAXN],tree[MAXN*4],add[MAXN*4],mui[MAXN*4];
//add加
//mui乘
void up(int root){
tree[root]=(tree[root<<1]+tree[root<<1 | 1])%p;
}
void down(int root,int l,int r){//***
int mid=(l+r)>>1;
int left_son=(root<<1);
int right_son=(root<<1 | 1);
if(mui[root]!=1){
mui[left_son]=(mui[left_son]*mui[root])%p;
mui[right_son]=(mui[right_son]*mui[root])%p;
add[left_son]=(add[left_son]*mui[root])%p;
add[right_son]=(add[right_son]*mui[root])%p;
tree[left_son]=(tree[left_son]*mui[root])%p;
tree[right_son]=(tree[right_son]*mui[root])%p;
mui[root]=1;
}
if(add[root]){
tree[left_son]=(tree[left_son]+add[root]*(mid-l+1))%p;
tree[right_son]=(tree[right_son]+add[root]*(r-mid))%p;
add[left_son]=(add[left_son]+add[root])%p;
add[right_son]=(add[right_son]+add[root])%p;
add[root]=0;
}
}
void build(int root,int l,int r){
add[root]=0;
mui[root]=1;
if(l==r){
tree[root]=a[l];
return;
}
int mid=(l+r)>>1;
down(root,l,r);
build(root<<1,l,mid);
build(root<<1 | 1,mid+1,r);
up(root);
}
void Add(int root,int l,int r,int ql,int qr,long long x){
if(l>=ql && r<=qr){
tree[root]=(tree[root]+x*(r-l+1))%p;
add[root]=(add[root]+x)%p;
return;
}
int mid=(l+r)>>1;
down(root,l,r);
if(ql<=mid) Add(root<<1,l,mid,ql,qr,x);
if(qr>mid) Add(root<<1 | 1,mid+1,r,ql,qr,x);
up(root);
}
void Mui(int root,int l,int r,int ql,int qr,long long x){
if(l>=ql&&r<=qr){
tree[root]=(tree[root]*x)%p;
add[root]=(add[root]*x)%p;
mui[root]=(mui[root]*x)%p;
return;
}
int mid=(l+r)>>1;
down(root,l,r);
if(ql<=mid) Mui(root<<1,l,mid,ql,qr,x);
if(qr>mid) Mui(root<<1 | 1,mid+1,r,ql,qr,x);
up(root);
}
long long getsum(int root,int l,int r,int ql,int qr){
if(l>=ql && r<=qr){
return tree[root];
}
int mid=(l+r)>>1;
long long res=0;
down(root,l,r);
if(ql<=mid) res+=getsum(root<<1,l,mid,ql,qr);
if(qr>mid) res+=getsum(root<<1 | 1,mid+1,r,ql,qr);
up(root);
return res%p;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>m>>p;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=1;i<=m;i++){
int op,x1,y1;
long long k;
cin>>op;
if(op==1){
cin>>x1>>y1>>k;
Mui(1,1,n,x1,y1,k);
}else if(op==2){
cin>>x1>>y1>>k;
Add(1,1,n,x1,y1,k);
} else {
cin>>x1>>y1;
cout<<getsum(1,1,n,x1,y1)<<"\n";
}
}
}