MnZn-线段树模板求助
查看原帖
MnZn-线段树模板求助
430409
Coros_Trusds楼主2022/1/2 14:42
//2022/1/2

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

#include <cstdio>

#include <climits>//need "INT_MAX","INT_MIN"

#include <cstring>//need "memset"

#define int long long

#define enter() putchar(10)

#define debug(c,que) cerr<<#c<<" = "<<c<<que

#define cek(c) puts(c)

#define blow(arr,st,ed,w) for(register int i=(st);i<=(ed);i++)cout<<arr[i]<<w;

#define speed_up() cin.tie(0),cout.tie(0)

#define endl "\n"

#define Input_Int(n,a) for(register int i=1;i<=n;i++)scanf("%d",a+i);

#define Input_Long(n,a) for(register long long i=1;i<=n;i++)scanf("%lld",a+i);

#define mst(a,k) memset(a,k,sizeof(a))

namespace Newstd
{
	inline int read()
	{
		int x=0,k=1;
		char ch=getchar();
		while(ch<'0' || ch>'9')
		{
			if(ch=='-')
			{
				k=-1;
			}
			ch=getchar();
		}
		while(ch>='0' && ch<='9')
		{
			x=(x<<1)+(x<<3)+ch-'0';
			ch=getchar();
		}
		return x*k;
	}
	inline void write(int x)
	{
		if(x<0)
		{
			putchar('-');
			x=-x;
		}
		if(x>9)
		{
			write(x/10);
		}
		putchar(x%10+'0');
	}
}

using namespace Newstd;

using namespace std;

const int ma=1e5+5;

int a[ma];

int sum[ma<<2],add[ma<<2],mul[ma<<2];

int n,m,mod;

namespace Segment_Tree
{
	#define ls(p) (p<<1)
	
	#define rs(p) (p<<1|1)
	
	inline void pushup(int p)
	{
		sum[p]=(sum[ls(p)]+sum[rs(p)])%mod;
	} 
	
	inline void build(int p,int l,int r)
	{
		mul[p]=1;
		
		if(l==r)
		{
			sum[p]=a[l]%mod;
			
			return;
		}
		
		int mid=(l+r)>>1;
		
		Segment_Tree::build(ls(p),l,mid);
		
		Segment_Tree::build(rs(p),mid+1,r);
		
		Segment_Tree::pushup(p);
	}
	
	inline void pushdown(int p,int l,int r)
	{
		int mid=(l+r)>>1;
		
		sum[ls(p)]=(sum[ls(p)]*mul[p]+add[p]*(mid-l+1))%mod;
		
		sum[rs(p)]=(sum[rs(p)]*mul[p]+add[p]*(r-mid))%mod;
		
		mul[ls(p)]=(mul[ls(p)]*mul[p])%mod;
		
		mul[rs(p)]=(mul[rs(p)]*mul[p])%mod;
		
		add[ls(p)]=(add[ls(p)]*mul[p]+add[p])%mod;
		
		add[rs(p)]=(add[rs(p)]*mul[p]+add[p])%mod;
		
		add[p]=0,mul[0]=1;
	}
	
	inline void updata(int nl,int nr,int l,int r,int p,int k,int opt)
	{
		if(nl<=l && r<=nr)
		{
			if(opt==1)
			{
				add[p]=(add[p]*k)%mod;
				
				mul[p]=(mul[p]*k)%mod;
				
				sum[p]=(sum[p]*k)%mod;
			}
			
			else
			{
				add[p]=(add[p]+k)%mod;
				
				sum[p]=(sum[p]+k*(r-l+1))%mod;
			}
			
			return; 
		}
		
		Segment_Tree::pushdown(p,l,r);
		
		int mid=(l+r)>>1;
		
		if(nl<=mid)
		{
			Segment_Tree::updata(nl,nr,l,mid,ls(p),k,opt);
		}
		
		if(nr>mid)
		{
			Segment_Tree::updata(nl,nr,mid+1,r,rs(p),k,opt);
		}
		
		Segment_Tree::pushup(p);
	}
	
	inline int query(int nl,int nr,int l,int r,int p)
	{
		if(nl<=l && r<=nr)
		{
			return sum[p];
		}
		
		Segment_Tree::pushdown(p,l,r);
		
		int mid=(l+r)>>1,res=0;
		
		if(nl<=mid)
		{
			res=(res+Segment_Tree::query(nl,nr,l,mid,ls(p)))%mod;
		}
		
		if(nr>mid)
		{
			res=(res+Segment_Tree::query(nl,nr,mid+1,r,rs(p)))%mod;
		}
		
		return res;
	}
	
	#undef ls
	
	#undef rs
}

#undef int

int main(void)
{
	#define int long long
	
	n=read(),m=read(),mod=read();
	
	Input_Long(n,a);
	
	Segment_Tree::build(1,1,n); 
	
	while(m--)
	{
		int opt=read(),x=read(),y=read();
		
		if(opt==1)
		{
			int k=read();
			
			Segment_Tree::updata(x,y,1,n,1,k,opt);
		}
		
		else if(opt==2)
		{
			int k=read();
			
			Segment_Tree::updata(x,y,1,n,1,k,opt);
		}
		
		else
		{
			printf("%lld\n",Segment_Tree::query(x,y,1,n,1));
		}
	}
	
	return 0;
}
2022/1/2 14:42
加载中...