加法和乘法标记,处理方法:
加法时直接添加标记,乘法时将加法标记也进行修改,在标记下放时,先放乘法(直接乘),再放加法(直接加),放乘法标记时要同时修改加法标记。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
ll read(){
ll w=1,q=0;char ch=' ';
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')q=(ll)q*10+ch-'0',ch=getchar();
return (ll)w*q;
}
int n,m;
ll mod;
ll a[100005],sum[400005],mul[400005],laz[400005];
void up(int i){sum[i]=(sum[(i<<1)]+sum[(i<<1)|1])%mod;}
void pd(int i,int s,int t){
int l=(i<<1),r=(i<<1)|1,mid=(s+t)>>1;
if(mul[i]!=1){
mul[l]*=mul[i];mul[l]%=mod;mul[r]*=mul[i];mul[r]%=mod;
laz[l]*=mul[i];laz[l]%=mod;laz[r]*=mul[i];laz[r]%=mod;
sum[l]*=mul[i];sum[l]%=mod;sum[r]*=mul[i];sum[r]%=mod;
mul[i]=1;
}
if(laz[i]){
sum[l]+=laz[i]*(mid-s+1);sum[l]%=mod;
sum[r]+=laz[i]*(t-mid);sum[r]%=mod;
laz[l]+=laz[i];laz[l]%=mod;
laz[r]+=laz[i];laz[r]%=mod;
laz[i]=0;
}return;
}
void build(int s,int t,int i){
mul[i]=1;if(s==t){sum[i]=a[s];return;}
int mid=(s+t)>>1;
build(s,mid,i<<1);build(mid+1,t,(i<<1)|1);up(i);
}
void chen(int l,int r,int s,int t,int i,ll z){
int mid=(s+t)>>1;
if(l<=s&&t<=r){
mul[i]*=z;mul[i]%=mod;laz[i]*=z;laz[i]%=mod;
sum[i]*=z;sum[i]%=mod;return;
}
pd(i,s,t);
if(mid>=l)chen(l,r,s,mid,(i<<1),z);
if(mid+1<=r)chen(l,r,mid+1,t,(i<<1)|1,z);
up(i);
}
void add(int l,int r,int s,int t,int i,ll z){
int mid=(s+t)>>1;
if(l<=s&&t<=r){
sum[i]+=z*(t-s+1);sum[i]%=mod;laz[i]+=z;laz[i]%=mod;
return;
}
pd(i,s,t);
if(mid>=l)add(l,r,s,mid,(i<<1),z);
if(mid+1<=r)add(l,r,mid+1,t,(i<<1)|1,z);
up(i);
}
ll getans(int l,int r,int s,int t,int i){
int mid=(s+t)>>1;ll tot=0;
if(l<=s&&t<=r){return sum[i];}
pd(i,s,t);
if(mid>=l)tot+=getans(l,r,s,mid,(i<<1));
tot%=mod;
if(mid+1<=r)tot+=getans(l,r,mid+1,t,(i<<1)|1);
return tot%mod;
}
int main()
{
int i,j,x,y,bh;
ll z;
n=read();m=read();mod=read();
for(i=1;i<=n;i++)a[i]=read();
build(1,n,1);
for(i=1;i<=m;i++){
bh=read();
if(bh==1){
x=read();y=read();z=read();
chen(x,y,1,n,1,z);
}
else if(bh==2){
x=read();y=read();z=read();
add(x,y,1,n,1,z);
}
else if(bh==3){
x=read();y=read();
printf("%lld\n",getans(x,y,1,n,1));
}
}
return 0;
}
加法标记和区间赋值标记,修改区间赋值标记时将加法标记变成0,修改加法标记时直接改。下放时先放区间赋值标记,同时把儿子的加法标记变为0,再下放加法标记。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
const int SN=400005;
ll read(){
char ch=' ';ll w=1,q=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')q=(ll)q*10+ch-'0',ch=getchar();
return (ll)w*q;
}
int n,m;
ll a[100005],sum[SN],maxx[SN],minn[SN],se[SN],laz[SN];
void up(int i){
int l=(i<<1),r=(i<<1)|1;
sum[i]=sum[l]+sum[r];
maxx[i]=max(maxx[l],maxx[r]);
minn[i]=min(minn[l],minn[r]);
}
void pd(int i,int s,int t){
int l=(i<<1),r=(i<<1)|1,mid=(s+t)>>1;
if(se[i]>=0){//如果有add标记,说明是set后面的
sum[l]=(ll)(mid-s+1)*se[i];sum[r]=(ll)(t-mid)*se[i];
maxx[l]=se[i];maxx[r]=se[i];
minn[l]=se[i];minn[r]=se[i];
laz[l]=0;laz[r]=0;se[l]=se[i];se[r]=se[i];
se[i]=-1;
}
if(laz[i]){
sum[l]+=(ll)(mid-s+1)*laz[i];sum[r]+=(ll)(t-mid)*laz[i];
maxx[l]+=laz[i];maxx[r]+=laz[i];
minn[l]+=laz[i];minn[r]+=laz[i];
laz[l]+=laz[i];laz[r]+=laz[i];laz[i]=0;
}
}
void build(int s,int t,int i){
se[i]=-1;if(s==t){sum[i]=maxx[i]=minn[i]=a[s];return;}
int mid=(s+t)>>1;
build(s,mid,(i<<1));build(mid+1,t,(i<<1)|1);up(i);
}
void add(int l,int r,int s,int t,int i,ll z){
if(l<=s&&t<=r){
sum[i]+=(ll)z*(t-s+1);maxx[i]+=z;minn[i]+=z;
laz[i]+=z;return;
}
pd(i,s,t);int mid=(s+t)>>1;
if(mid>=l)add(l,r,s,mid,(i<<1),z);
if(mid+1<=r)add(l,r,mid+1,t,(i<<1)|1,z);up(i);
}
void chan(int l,int r,int s,int t,int i,ll z){
if(l<=s&&t<=r){
sum[i]=(ll)z*(t-s+1);maxx[i]=z;minn[i]=z;
laz[i]=0;se[i]=z;return;
}
pd(i,s,t);int mid=(s+t)>>1;
if(mid>=l)chan(l,r,s,mid,(i<<1),z);
if(mid+1<=r)chan(l,r,mid+1,t,(i<<1)|1,z);up(i);
}
ll getsum(int l,int r,int s,int t,int i){
if(l<=s&&t<=r)return sum[i];
pd(i,s,t);int mid=(s+t)>>1;ll tot=0;
if(mid>=l)tot+=getsum(l,r,s,mid,(i<<1));
if(mid+1<=r)tot+=getsum(l,r,mid+1,t,(i<<1)|1);
return tot;
}
ll getmin(int l,int r,int s,int t,int i){
if(l<=s&&t<=r)return minn[i];
pd(i,s,t);int mid=(s+t)>>1;ll tot=LLONG_MAX;
if(mid>=l)tot=getmin(l,r,s,mid,(i<<1));
if(mid+1<=r)tot=min(tot,getmin(l,r,mid+1,t,(i<<1)|1));
return tot;
}
ll getmax(int l,int r,int s,int t,int i){
if(l<=s&&t<=r)return maxx[i];
pd(i,s,t);int mid=(s+t)>>1;ll tot=LLONG_MIN;
if(mid>=l)tot=getmax(l,r,s,mid,(i<<1));
if(mid+1<=r)tot=max(tot,getmax(l,r,mid+1,t,(i<<1)|1));
return tot;
}
int main()
{
int i,j,x,y;char ch;ll z;
n=read();m=read();
for(i=1;i<=n;i++)a[i]=read();
build(1,n,1);
for(i=1;i<=m;i++){
ch=' ';
while(ch<'a'||ch>'z')ch=getchar();
if(ch=='a'){x=read();y=read();z=read();add(x,y,1,n,1,z);}
else if(ch=='s'){
ch=getchar();
if(ch=='e'){x=read();y=read();z=read();chan(x,y,1,n,1,z);}
else {x=read();y=read();printf("%lld\n",getsum(x,y,1,n,1));}
}
else if(ch=='m'){
ch=getchar();
if(ch=='i'){x=read();y=read();printf("%lld\n",getmin(x,y,1,n,1));}
else {x=read();y=read();printf("%lld\n",getmax(x,y,1,n,1));}
}
}
return 0;
}