「模板」 线段树——区间乘 && 区间加 && 区间求和

「模板」 线段树——区间乘 && 区间加 && 区间求和

<题目链接>


原来的代码太恶心了,重贴一遍。

#include <cstdio>
int n,m;
long long p;
class SegmentTree
{
	private:
		struct Node
		{
			int l,r;
			long long v,mul,add;
			Node *c[2];
			Node(int l,int r):l(l),r(r),mul(1LL),add(0LL)
			{
				c[0]=c[1]=nullptr;
			}
			~Node(void)
			{
				if(c[0]!=nullptr)
					delete c[0];
				if(c[1]!=nullptr)
					delete c[1];
			}
			long long Size(void)
			{
				return (long long)(r-l+1);
			}
			long long Value(bool p)
			{
				return c[p]!=nullptr ? c[p]->v : 0;
			}
			void Modify(long long _mul,long long _add)
			{
				v=(v*_mul+Size()*_add)%p;
				mul=mul*_mul%p;
				add=(add*_mul+_add)%p;
			}
			void MulModify(long long k)
			{
				v=v*k%p;
				mul=mul*k%p;
				add=add*k%p;
			}
			void AddModify(long long k)
			{
				v=(v+Size()*k)%p;
				add=(add+k)%p;
			}
			void PushUp(void)
			{
				v=(Value(0)+Value(1))%p;
			}
			void PushDown(void)
			{
				if(c[0]!=nullptr)
					c[0]->Modify(mul,add);
				if(c[1]!=nullptr)
					c[1]->Modify(mul,add);
				mul=1,add=0;
			}
		}*rt;
		void Build(Node* &i,int l,int r)
		{
			i=new Node(l,r);
			if(l==r)
			{
				scanf("%lld",&i->v);
				return;
			}
			int mid=l+r>>1;
			Build(i->c[0],l,mid);
			Build(i->c[1],mid+1,r);
			i->PushUp();
		}
		void Mul(Node* i,int l,int r,long long k)
		{
			if(l==i->l && r==i->r)
			{
				i->MulModify(k);
				return;
			}
			i->PushDown();
			int mid=i->l+i->r>>1;
			if(r<=mid)
				Mul(i->c[0],l,r,k);
			else if(l>mid)
				Mul(i->c[1],l,r,k);
			else
			{
				Mul(i->c[0],l,mid,k);
				Mul(i->c[1],mid+1,r,k);
			}
			i->PushUp();
		}
		void Add(Node* i,int l,int r,long long k)
		{
			if(l==i->l && r==i->r)
			{
				i->AddModify(k);
				return;
			}
			i->PushDown();
			int mid=i->l+i->r>>1;
			if(r<=mid)
				Add(i->c[0],l,r,k);
			else if(l>mid)
				Add(i->c[1],l,r,k);
			else
			{
				Add(i->c[0],l,mid,k);
				Add(i->c[1],mid+1,r,k);
			}
			i->PushUp();
		}
		long long Sum(Node* i,int l,int r)
		{
			if(l==i->l && r==i->r)
				return i->v;
			i->PushDown();
			int mid=i->l+i->r>>1;
			if(r<=mid)
				return Sum(i->c[0],l,r);
			else if(l>mid)
				return Sum(i->c[1],l,r);
			else
				return (Sum(i->c[0],l,mid)+Sum(i->c[1],mid+1,r))%p;
		}
	public:
		SegmentTree(int n):rt(nullptr)
		{
			Build(rt,1,n);
		}
		~SegmentTree(void)
		{
			delete rt;
		}
		void Mul(int l,int r)
		{
			long long k;
			scanf("%lld",&k);
			Mul(rt,l,r,k);
		}
		void Add(int l,int r)
		{
			long long k;
			scanf("%lld",&k);
			Add(rt,l,r,k);
		}
		void Sum(int l,int r)
		{
			printf("%lld\n",Sum(rt,l,r));
		}
};
int main(int argc,char** argv)
{
	scanf("%d %d %lld",&n,&m,&p);
	static SegmentTree *T=new SegmentTree(n);
	for(int i=1,opt,x,y;i<=m;++i)
	{
		scanf("%d %d %d",&opt,&x,&y);
		switch(opt)
		{
			case 1:
				T->Mul(x,y);
				break;
			case 2:
				T->Add(x,y);
				break;
			case 3:
				T->Sum(x,y);
				break;
		}
	}
	delete T;
	return 0;
}

谢谢阅读。

posted @ 2018-05-28 22:22  Capella  阅读(262)  评论(0编辑  收藏  举报

谢谢光临