有个奇妙的想法
查看原帖
有个奇妙的想法
893704
lingquan楼主2024/12/4 23:04

在写需要多个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;
}
2024/12/4 23:04
加载中...