洛谷 P3373 【模板】线段树 2

对懒标记的理解更深入了
#include<bits/stdc++.h>
using namespace std;

#define int long long

typedef pair<int,int> PII;

const int N = 1e5+10;

int n,m,p;
int a[N];

struct NODE{
	int l,r;
	int sum;
	int add,mul;
}tr[N*4];

void pushup(int u){
	tr[u].sum=(tr[u<<1].sum+tr[u<<1|1].sum)%p;
}

void pushdown(int u){
	int x=u<<1,y=u<<1|1;
	tr[x].sum=(tr[x].sum*tr[u].mul+tr[u].add*(tr[x].r-tr[x].l+1))%p;
	tr[x].add=(tr[x].add*tr[u].mul+tr[u].add)%p;
	tr[x].mul=(tr[x].mul*tr[u].mul)%p;
	tr[y].sum=(tr[y].sum*tr[u].mul+tr[u].add*(tr[y].r-tr[y].l+1))%p;
	tr[y].add=(tr[y].add*tr[u].mul+tr[u].add)%p;
	tr[y].mul=(tr[y].mul*tr[u].mul)%p;
	tr[u].add=0;
	tr[u].mul=1;
}

void build(int u,int l,int r){
	if(l==r){
		tr[u]={l,l,a[l],0,1};
		return;
	}
	tr[u].l=l,tr[u].r=r,tr[u].add=0,tr[u].mul=1;
	int mid=l+r>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	pushup(u);
}

int query(int u,int l,int r){
	if(l<=tr[u].l && r>=tr[u].r) return tr[u].sum;
	else{
		pushdown(u);
		int mid=tr[u].l+tr[u].r>>1;
		if(r<=mid) return query(u<<1,l,r);
		else if(l>mid) return query(u<<1|1,l,r);
		else{
			int suml=query(u<<1,l,r),sumr=query(u<<1|1,l,r);
			return suml+sumr;
		}
	}
}

void modify(int u,int l,int r,int d,int flag){
	if(l<=tr[u].l && r>=tr[u].r){
		if(flag){
			tr[u].sum=(tr[u].sum+(tr[u].r-tr[u].l+1)*d)%p;	
			tr[u].add=(tr[u].add+d)%p;
		} 
		else{
			tr[u].sum=tr[u].sum*d%p;
			tr[u].add=tr[u].add*d%p;
			tr[u].mul=tr[u].mul*d%p;
		} 
	}
	else{
		pushdown(u);
		int mid=tr[u].l+tr[u].r>>1;
		if(r<=mid) modify(u<<1,l,r,d,flag);
		else if(l>mid) modify(u<<1|1,l,r,d,flag);
		else{
			modify(u<<1,l,r,d,flag);
			modify(u<<1|1,l,r,d,flag);
		}
		pushup(u);
	}
}

signed main(){
	cin>>n>>m>>p;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	int op;
	while(m--){
		scanf("%lld",&op);
		if(op==3){
			int l,r;
			cin>>l>>r;
			cout<<query(1,l,r)%p<<endl;
		}
		else{
			int l,r,d;
			cin>>l>>r>>d;
			if(op==1) modify(1,l,r,d,0);
			else modify(1,l,r,d,1);
		}
	}
	return 0;
}
posted @ 2022-06-17 23:59  xhy666  阅读(49)  评论(0)    收藏  举报