在写需要多个lazy的时候想到的一种方法
对于不同的lazy,只保留最后一次操作的lazy
也就是如果有不同类型的操作,把已有的lazy传下去, 而在本层lazy保留现有的同类型操作
在1到10的数组里
我对1到4的数加3
再对1到4乘4
那加3的lazytag会传到1到2 和 3到4的区间里
1到4的区间只有乘4的lazy
但这种方法能不能实现?
(虽然似乎效率低下)
附上本蒟蒻的错误 (期望正确) 的代码:
#include <bits/stdc++.h>
#define add te[u].sum=(te[u<<1].sum+te[u<<1|1].sum)%k
using namespace std;
const int N=1e5+5;
int a[N];
int n,m;
int k;
struct node{
long long sum;
long long lzadd;
long long lzmul=1;
int l,r;
}te[N<<2];
inline void pushdownmul(int u);
void build(int u,int l,int r){
te[u].l=l,te[u].r=r;
if(l==r){
te[u].sum=a[l];
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
add;
return;
}
inline void pushdownadd(int u){
if(te[u].lzadd==0){
return;
}
pushdownmul(u);
int l=te[u].l,r=te[u].r,w=te[u].lzadd;
int mid=(l+r)>>1;
te[u<<1].sum=(te[u<<1].sum+(mid-l+1)*w)%k;
te[u<<1|1].sum=(te[u<<1|1].sum+(r-mid)*w)%k;
te[u<<1].lzadd=(te[u<<1].lzadd+w)%k;
te[u<<1|1].lzadd=(te[u<<1|1].lzadd+w)%k;
te[u].lzadd=0;
return;
}
inline void pushdownmul(int u){
if(te[u].lzmul==0){
return;
}
pushdownadd(u);
int l=te[u].l,r=te[u].r,w=te[u].lzmul;
int mid=(l+r)>>1;
te[u<<1].sum*=w%k;
te[u<<1|1].sum*=w%k;
te[u<<1].lzmul*=w%k;
te[u<<1|1].lzmul*=w%k;
te[u].lzmul=0;
return;
}
void updateadd(int u,int x,int y,int w){
int l=te[u].l,r=te[u].r;
if(x<=l && y>=r){
pushdownmul(u);
te[u].lzadd=(te[u].lzadd+w)%k;
te[u].sum=(te[u].sum+(r-l+1)*w)%k;
return;
}
pushdownadd(u);
int mid=(l+r)>>1;
if(x<=mid){
updateadd(u<<1,x,mid,w);
}
if(y>mid){
updateadd(u<<1|1,mid+1,r,w);
}
add;
return;
}
void updatemul(int u,int x,int y,int w){
int l=te[u].l,r=te[u].r;
if(x<=l && y>=r){
pushdownadd(u);
te[u].lzmul=(te[u].lzmul+w)%k;
te[u].sum*=w%k;
return;
}
pushdownmul(u);
int mid=(l+r)>>1;
if(x<=mid){
updatemul(u<<1,x,mid,w);
}
if(y>mid){
updatemul(u<<1|1,mid+1,y,w);
}
add;
return;
}
long long query(int u,int x,int y){
int l=te[u].l,r=te[u].r;
if(x<=l && y>=r){
return te[u].sum%k;
}
pushdownadd(u);pushdownmul(u);
int mid=(l+r)>>1;
long long sum=0;
if(x<=mid){
sum+=query(u<<1,x,mid);
}
sum%=k;
if(y>mid){
sum+=query(u<<1|1,mid+1,r);
}
return sum%k;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
for(int i=1;i<=m;i++){
int c,x,y;
int k;
scanf("%d%d%d",&c,&x,&y);
if(c==1){
scanf("%d",&k);
updateadd(1,x,y,k);
}else if(c==2){
scanf("%d",&k);
updatemul(1,x,y,k);
}else{
printf("%lld\n",query(1,x,y));
}
}
return 0;
}