P3373 【模板】线段树 2

题目

P3373 【模板】线段树 2_第1张图片

思路

作为线段树模板题,这题主要考查了对lazytag以及先乘后加的使用,
因为是模板,所以这里证明略

代码

#include
using namespace std;
#define int long long
const int maxn=1e5+5;
int n,m,p;
int a[maxn];
struct node{
	int v,mul,add;
}st[maxn*4];
//初始化
void init(int root,int l,int r){
	st[root].mul=1,st[root].add=0;
	if(l==r) st[root].v=a[l];
	else { int mid=l+r>>1;init(root*2,l,mid),init(root*2+1,mid+1,r),st[root].v=st[root*2].v+st[root*2+1].v; }
	st[root].v%=p;
	return;
}
void pushdown(int root,int l,int r){
    int mid=(l+r)/2;
    st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(mid-l+1))%p,st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-mid))%p,st[root*2].mul=(st[root*2].mul*st[root].mul)%p,st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p,st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p,st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p,st[root].mul=1,st[root].add=0;
    return;
}
//加
void ud1(int root,int stdl,int stdr,int l,int r,int k){
    if(r<stdl||stdr<l) return;
    if(l<=stdl&&stdr<=r) { st[root].v=(st[root].v*k)%p,st[root].mul=(st[root].mul*k)%p,st[root].add=(st[root].add*k)%p;return; }
    pushdown(root,stdl,stdr);
    int mid=stdl+stdr>>1;
    ud1(root*2,stdl,mid,l,r,k),ud1(root*2+1,mid+1,stdr,l,r,k);
    st[root].v=(st[root*2].v+st[root*2+1].v)%p;
    return;
}
//乘
void ud2(int root,int stdl,int stdr,int l,int r,int k){
    if(r<stdl||stdr<l) return;
    if(l<=stdl&&stdr<=r){
		st[root].add=(st[root].add+k)%p,st[root].v=(st[root].v+k*(stdr-stdl+1))%p;
        return;
    }
    pushdown(root,stdl,stdr);
    int mid=stdl+stdr>>1;
    ud2(root*2,stdl,mid,l,r,k),ud2(root*2+1,mid+1,stdr,l,r,k);
    st[root].v=(st[root*2].v+st[root*2+1].v)%p;
    return;
}
//查询区间和
int query(int root,int stdl,int stdr,int l,int r){
    if(r<stdl||stdr<l) return 0;
    if(l<=stdl&&stdr<=r) return st[root].v;
    pushdown(root,stdl,stdr);
    int mid=(stdl+stdr)/2;
    return (query(root*2,stdl,mid,l,r)+query(root*2+1,mid+1,stdr,l,r))%p;
}
signed main(){
	cin>>n>>m>>p;
    for(int i=1;i<=n;i++) cin>>a[i];
    init(1,1,n);
    while(m--){
        int if_case;cin>>if_case;
        int x,y,k;
        switch (if_case){
        	case 1:cin>>x>>y>>k;ud1(1,1,n,x,y,k);break;
        	case 2:cin>>x>>y>>k;ud2(1,1,n,x,y,k);break;
        	case 3:cin>>x>>y;cout<<query(1,1,n,x,y)<<endl;break;
		}
    }
    return 0;
}

end

完结撒花

你可能感兴趣的:(算法,数据结构,线段树,c++)