「模板」 线段树——区间乘 && 区间加 && 区间求和
「模板」 线段树——区间乘 && 区间加 && 区间求和
原来的代码太恶心了,重贴一遍。
#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;
}
谢谢阅读。
「模板」 线段树——区间乘 && 区间加 && 区间求和的更多相关文章
- Loj #2570. 「ZJOI2017」线段树
		Loj #2570. 「ZJOI2017」线段树 题目描述 线段树是九条可怜很喜欢的一个数据结构,它拥有着简单的结构.优秀的复杂度与强大的功能,因此可怜曾经花了很长时间研究线段树的一些性质. 最近可怜 ... 
- 「ZJOI2019」线段树 解题报告
		「ZJOI2019」线段树 听说有人喷这个题简单,然后我就跑去做,然后自闭感++,rp++(雾) 理性分析一波,可以发现最后形成的\(2^k\)个线段树,对应的操作的一个子集,按时间顺序作用到这颗线段 ... 
- 【LOJ】#3043. 「ZJOI2019」线段树
		LOJ#3043. 「ZJOI2019」线段树 计数转期望的一道好题-- 每个点设两个变量\(p,q\)表示这个点有\(p\)的概率有标记,有\(q\)的概率到祖先的路径上有个标记 被覆盖的点$0.5 ... 
- LOJ 3043: 洛谷 P5280: 「ZJOI2019」线段树
		题目传送门:LOJ #3043. 题意简述: 你需要模拟线段树的懒标记过程. 初始时有一棵什么标记都没有的 \(n\) 阶线段树. 每次修改会把当前所有的线段树复制一份,然后对于这些线段树实行一次区间 ... 
- 「ZJOI2019」线段树
		传送门 Description 线段树的核心是懒标记,下面是一个带懒标记的线段树的伪代码,其中 tag 数组为懒标记: 其中函数\(Lson(Node)\)表示\(Node\)的左儿子,\(Rson( ... 
- @loj - 2093@ 「ZJOI2016」线段树
		目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Yuuka 遇到了一个题目:有一个序列 a1,a2,..., ... 
- 【LOJ3043】「ZJOI2019」线段树
		题面 问题可以转化为每次区间覆盖操作有 \(\frac{1}{2}\) 的概率进行,求标记和的期望.于是我们只要求出所有点有标记的概率即可. 我们设 \(f_i\) 表示节点 \(i\) 有标记的概率 ... 
- @loj - 3043@「ZJOI2019」线段树
		目录 @description@ @solution@ @accepted code@ @details@ @description@ 九条可怜是一个喜欢数据结构的女孩子,在常见的数据结构中,可怜最喜 ... 
- poj 3468 A Simple Problem with Integers (线段树 成段更新 加值 求和)
		题目链接 题意: 只有这两种操作 C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.&quo ... 
随机推荐
- ZOJ 3644 Kitty's Game(数论+DP)
			Description Kitty is a little cat. She is crazy about a game recently. There arenscenes in the game( ... 
- HDU 1512 Monkey King(左偏树)
			Description Once in a forest, there lived N aggressive monkeys. At the beginning, they each does thi ... 
- 使用libpcab抓包&处理包
			#include <stdio.h> #include <stdlib.h> #include <strings.h> #include <string.h& ... 
- string && 字符数组
			一.string 1. 使用字符串字面值初始化string对象 如:string s1 = "hiya"; string s2("hiya"); 该字面值的最后 ... 
- 11.24Daily Scrum(4)
			人员 任务分配完成情况 明天任务分配 王皓南 实现网页上视频浏览的功能.研究相关的代码和功能.1007 实现视频浏览的功能 申开亮 实现网页上视频浏览的功能.研究相关的代码和功能.1008 实现视频浏 ... 
- Coursera:Internet History ,Techornology and Security
			WEEK1 War Time Computing and Communication Bletchley Park 布莱彻利庄园:a top-secret code breaking effort b ... 
- iOS APP中第三方APP调用自己的APP,打开文件
			根据需求需要在项目中要打开word.pdf.excel等文件,在info.plist文件中添加 <key>CFBundleDocumentTypes</key> <arr ... 
- <Effective C++>读书摘要--Implementations<一>
			1.For the most part, coming up with appropriate definitions for your classes (and class templates) a ... 
- hadoop2.5.2学习及实践笔记(五)—— HDFS shell命令行常见操作
			附:HDFS shell guide文档地址 http://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-common/FileSy ... 
- PAT L1-044 稳赢
			https://pintia.cn/problem-sets/994805046380707840/problems/994805086365007872 大家应该都会玩“锤子剪刀布”的游戏:两人同时 ... 
