原来一直没弄懂为什么pushdown要先乘后加,然后直接写四个数演示了一遍懂了,先乘后加时,在算加时发现,add经过mul已经翻倍了,就能弥补一开始加的。
image

#define ll long long
#define lc p<<1
#define rc p<<1|1
using namespace std;
const int N=1e5+5;
ll pp;
struct node{
	int l;
	int r;
	ll sum;
	ll add;
	ll mul;
}tree[N<<2];
ll w[N];
void pushup(int p){
	tree[p].sum=(tree[lc].sum+tree[rc].sum)%pp;
}
void pushdown(int p){
	if(tree[p].add!=0||tree[p].mul!=1){
		tree[lc].sum = (tree[lc].sum * tree[p].mul % pp + (tree[lc].r - tree[lc].l + 1) * tree[p].add % pp) % pp;
		tree[rc].sum = (tree[rc].sum * tree[p].mul % pp + (tree[rc].r - tree[rc].l + 1) * tree[p].add % pp) % pp;
		tree[lc].add = (tree[p].mul * tree[lc].add + tree[p].add) % pp;
		tree[rc].add = (tree[p].mul * tree[rc].add + tree[p].add) % pp;
		tree[lc].mul = (tree[p].mul * tree[lc].mul) % pp;
		tree[rc].mul = (tree[p].mul * tree[rc].mul) % pp;
		tree[p].mul = 1;
		tree[p].add = 0;
	}
	
}
void build(ll p,ll l,ll r){
	tree[p]={l,r,0,0,1};
	if(l==r){
		tree[p].sum=w[l]%pp;
		return;
	}
	int mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	pushup(p);
}

void update_add(int p,int x,int y,ll k){
	if(x<=tree[p].l&&y>=tree[p].r){
		tree[p].sum=(tree[p].sum+(tree[p].r-tree[p].l+1)*k)%pp;
		tree[p].add=(tree[p].add+k)%pp;
		return;
	}
	pushdown(p);
	int m=(tree[p].l+tree[p].r)>>1;
	if(x<=m)update_add(lc,x,y,k);
	if(y>m)update_add(rc,x,y,k);
	pushup(p);
}
void update_mul(int p,int x,int y,ll k){
	if(x>tree[p].r||y<tree[p].l)return;
	if(x<=tree[p].l&&tree[p].r<=y){
		tree[p].sum=(tree[p].sum*k)%pp;
		tree[p].mul=(tree[p].mul*k)%pp;
		tree[p].add=(tree[p].add*k)%pp;
		return;
	}
	pushdown(p);
	int mid=(tree[p].r+tree[p].l)/2;
	if(x<=mid)update_mul(lc,x,y,k);
	if(y>mid)update_mul(rc,x,y,k);
	pushup(p);
}
ll query(ll p,ll ql,ll qr){
	if(ql<=tree[p].l&&tree[p].r<=qr){
		return tree[p].sum%pp;
	}
	pushdown(p);
	ll m=(tree[p].l+tree[p].r)>>1;
	ll sum=0;
	if(ql<=m)sum=(sum+query(lc,ql,qr))%pp;
	if(qr>m)sum=(sum+query(rc,ql,qr))%pp;
	return sum;
}
int main(){
	int n,m;
	cin>>n>>m>>pp;
	for(int i=1;i<=n;i++){
		cin>>w[i];
	}
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int op;
		cin>>op;
		if(op==1){
			ll x,y,k;
			cin>>x>>y>>k;
			update_mul(1,x,y,k);
		}
		else if(op==2){
			ll x,y,k;
			cin>>x>>y>>k;
			update_add(1,x,y,k);
		}
		else if(op==3){
			ll x,y;
			cin>>x>>y;
			cout<<query(1,x,y)<<endl;
		}
	}
}```