HwH的线段树2(指针版)

#include<cstdio>

const int maxn=100005;
int p;
typedef long long int ll;

int n,q,m;
ll a[maxn];

struct Node
{
	ll tag1,tag2,v;
	int l,r;
	Node *ls,*rs;
	inline void maketag1(const ll w,const ll x)
	{
		v+=(r-l+1)%p*w%p;
		tag1=(tag1*x+w)%p;
	}
	inline void maketag2(const ll w)
	{
		v=v%p*w%p;
		tag2=tag2*w%p;
	}
	inline void pushup()
	{
		v=ls->v+rs->v;
		v%=p;
	}
	inline void pushdown()
	{
		if(tag1==0&&tag2==1) return;
		ls->maketag2(tag2);
		ls->maketag1(tag1,tag2);
		rs->maketag2(tag2);
		rs->maketag1(tag1,tag2);
		tag2=1,tag1=0;
	}
	Node(const int L,const int R)
	{
		l=L;r=R;
		if(l==r)
		{
			tag1=0;
			tag2=1;
			v=a[l]%p;
			ls=rs=NULL;
		}
		else
		{
			tag1=0;
			tag2=1;
			ll M=(L+R)>>1;
			ls=new Node(L,M);
			rs=new Node(M+1,R);
			pushup();
		}
	}
	
	inline bool InRange(const int L,const int R) {return (L<=l)&&(r<=R);}
	inline bool OutofRange(const int L,const int R) {return (l>R)||(r<L);}

	void upd1(const ll L,const ll R,const ll w)
	{
		if(InRange(L,R))
		{
			maketag1(w,1);
			return;
		}
		else if(!OutofRange(L,R))
		{
			pushdown();
			ls->upd1(L,R,w);
			rs->upd1(L,R,w);
			pushup();
		}
	}
	
	ll qry(const int L,const int R)
	{
		if(InRange(L,R)) return v%p;
		if(OutofRange(L,R)) return 0;
		pushdown();
		return (ls->qry(L,R)+rs->qry(L,R))%p;
	}
	
	void upd2(const int L,const int R,const ll w)
	{
		if(InRange(L,R))
		{
			maketag1(0,w);
			maketag2(w);
			return;
		}
		else if(!OutofRange(L,R))
		{
			pushdown();
			ls->upd2(L,R,w);
			rs->upd2(L,R,w);
			pushup();
		}
	}
};

int main()
{
	scanf("%d%d%d",&n,&q,&p);
	for(int i=1;i<=n;++i) scanf("%lld",a+i);
	Node *rot=new Node(1,n);
	for(ll o,x,y,z;q;--q)
	{
		scanf("%lld%lld%lld",&o,&x,&y);
		if(o==1)
		{
			scanf("%lld",&z);
			rot->upd2(x,y,z);
		}
		else if(o==2)
		{
			scanf("%lld",&z);
			rot->upd1(x,y,z);
		}
		else
		{
			printf("%lld\n",rot->qry(x,y));
		}
	}
	return 0;
}

  

posted @ 2020-07-01 15:28  国服混子瑶  阅读(124)  评论(0编辑  收藏  举报